日期:2014-05-20  浏览次数:20839 次

关于多线程的原子量的问题,希望大家一起讨论下,求结论
废话不多说,直接来代码,两个类
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;

public class MyCountA implements Runnable
{
  private static AtomicLong along = new AtomicLong(10000); //为什么这里要加static
  private String name;
  private int x;
  private Lock lock;
   
  public MyCountA(String name,int x,Lock lock)
  {
  this.name=name;
  this.x=x;
  this.lock=lock;
  }
  public void run(){
  lock.lock();
  System.out.println(name+"操作金额:"+x+"账户余额:"+along.addAndGet(x));
  lock.unlock();
  }
}



import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestM
{
  public static void main(String[] args)
  {
  Lock lock = new ReentrantLock(false);
  ExecutorService pool = Executors.newCachedThreadPool();
  Runnable t1 = new MyCountA("张三", 1000,lock);
  Runnable t2 = new MyCountA("李四", -1000,lock);
  Runnable t3 = new MyCountA("王五", 5000,lock);
  Runnable t4 = new MyCountA("赵六", -6000,lock);
  Runnable t5 = new MyCountA("阿大", 8000,lock);
  Runnable t6 = new MyCountA("阿三", -9000,lock);
  pool.execute(t6);
  pool.execute(t5);
  pool.execute(t4);
  pool.execute(t3);
  pool.execute(t2);
  pool.execute(t1);
  pool.shutdown();
  }
}

加static的话输出的答案正确:
阿三操作金额:-9000账户余额:1000
阿大操作金额:8000账户余额:9000
赵六操作金额:-6000账户余额:3000
张三操作金额:1000账户余额:4000
王五操作金额:5000账户余额:9000
李四操作金额:-1000账户余额:8000

不加static的话就得不到正确答案:
阿三操作金额:-9000账户余额:1000
阿大操作金额:8000账户余额:18000
赵六操作金额:-6000账户余额:4000
李四操作金额:-1000账户余额:9000
王五操作金额:5000账户余额:15000

不加的话每个人的操作全是针对10000这个值而言的,不知道是锁没有生效,这几个线程都在别的线程还没改变10000这个值的时候做的操作,还是每个线程对along 的值的修改无法对其他线程生效,还有就是原子量有什么用(说是可以保证变量操作的原子性,但整个程序还需要考虑线程安全的。)也就是在这里用原子量和普通的long 是没什么区别的,求达人解答

------解决方案--------------------
你这问题跟多线程无关,
就是static变量的事,

static变量是属于类的,不是某一个对像,也就是所有对像共用的变量,
非static就是一个对像一个
------解决方案--------------------

------解决方案--------------------
static 变量属于 类级的
------解决方案--------------------
这里是要加锁的,不加锁可能有两个线程同时执行,第二个线程执行along.addAndGet(),就把第一个线程的值改掉了。
至于为什么要加private static AtomicLong along 
如果不加的话,t1,t2...都是不同的MyCountA对象,那么操作的就是不同的along 变量了,加了static就是操作的同一个。
------解决方案--------------------
你们讨论我学习
------解决方案--------------------
因为Java的long不是C++的long,现在大多数C++的编译器,long是4个字节。
而Java的long是8个字节。那么32位的OS,一个指令最多处理4个字节。

也就说你 long a = 1;其实操作了两次,那么这两次就有可能被多线程cut。
所以一定要把 long当做一个原子量来操作。

幸好Java的lib提供了AtomicLong 。

就这么回事。