public class TaskA implements Runnable
{
private Operator operator;
private volatile int count = 0;
private ReentrantLock lock = new ReentrantLock();

public TaskA(Operator operator){
this.operator = operator;
}
public void run( )
{

while(true){
//lock.lock();
try{
Food f = new Food();
f.setName("apple"+count);
operator.put(f);
Thread.sleep(1000);
count++;
}
catch (InterruptedException e)
{
e.printStackTrace();
}finally{
//lock.unlock();
}
}
}}起2个线程往里放数据,得到结果
apple0
apple0
apple1
apple2
...
将volatile改用ReentrantLock,就能得到
apple0
apple1
apple2
apple3
...
貌似锁不住呀!哪位大侠帮我解释一下呀

解决方案 »

  1.   

    是你理解错volatile了,它没有你想象中那么强大。
      

  2.   

    volatile 是强制线程从共享内存中读取数据,而不是使用线程栈中的缓存。与数据更新完全是两码事,使用 volatile 可以使用一个线程更新了数据后,另一个线程能即刻看到,而不是要等很长时间才能看到。如果要使用不加同步、不加锁原子自增的话,可以使用 java.util.concurrent.atomic.AtomicInteger 的类。这个类直接使用 CPU 的 CAS 指令进行操作,
      

  3.   

    volatile除了具有可见性功能外,要代替锁操作的话,是要在一组严苛的前提环境下的
    同时满足两点:* 写给变量的值不能依赖它当前值
    * 变量不参与不变量与其它变量,即不能依赖其它程序的状态虽然这里给出的例子不足以证明volatile的非线程安全性,起初的连续两个0只是两个线程几乎同时读取count值而已,而这一点volatile是不会限制的吧?要证明的话,比如安排n(n足够大,比如1000)个线程去几乎同时执行count++操作
      

  4.   

    http://blog.csdn.net/jackieban/archive/2010/06/12/5665635.aspx看看这个或许对你有些帮助哦
      

  5.   

    volatile 修饰基本类型必须要确定变量操作是原子操作,
    但count++并不是原子操作,其中有读,加,写三个操作。
    但是count=0这种或者count的新值和旧值没有关联时才能用volatile。否则int 也要用同步块。
      

  6.   

    锁提供了两个主要功能:互斥与可见性
    而volatile主要特色是可见性,互斥的应用能力与synchronized相比要弱化很多(无法为count++提供thread-safe就是volatile无法为count++提供线程互斥),虽然volatile的优点是简单与性能
      

  7.   

    @ThreadSafe
    public class CheesyCounter {
        private volatile int value;    public int getValue() { return value; }    public synchronized int increment() {
            return value++;
        }
    }以上是volatile一个便宜读写锁的应用,用了volatile在读通道上同步的消耗要远低于synchronized locking的消耗,尤其在读操作要远多于写操作的情况下还有volatile在double-checked locking中的对单例对象instance修饰的作用就是属于对写原子化的一个例子
      

  8.   

    更正: 
    volatile变量有可见性特点,但没有原子性特点,double-checked locking中的用处public volatile Singleton instance;
    ...
    instance = new Singleton();只是保证volatile引用以既定发布的形态(as-published form)对其它线程可见,即对于instance而言,不会在某些线程提领(dereference)Singleton引用时冒风险得到一个部分构建了的Singleton对象但有个前提是被发布的对象须是线程安全或这说对象状态在发布后不变,否则就需要提供额外的同步措施
      

  9.   

    volatile不理解的话就不要乱用。免得出乱子
      

  10.   

    to bao110908thx!之前关注过 DCL 和 happen-before规则,没去了解过CAS 和 MSEI 协议,
    看了一下,果然不错。特别是 CAS 在多核时代通过使用 MESI protocol 优化了同步,而不用 lock system bus。有挺大收获。真是不错。
      

  11.   

    compare-and-swap or CAS.A CAS operation includes three parameters: a memory location, the expected old value, and a new value. The processor will update the location to the new value if the value that is there matches the expected old value; otherwise it will do nothing. It will return the value that was at that location prior to the CAS instruction. An example way to use CAS for synchronization is as following: public int increment () { 
        int oldValue = value.getValue(); 
        int newValue = oldValue + 1; 
        while (value.compareAndSwap(oldValue,newValue)!=oldValue) 
            oldValue = value.getValue(); 
        return oldValue + 1; 
    }First we read a value from the value, then perform a multi-step computation to derive a new value (this example is just increasing by one), and then use CAS to change the value of value from oldValue to the newValue. The CAS succeeds if the value at address has not been changed in the meantime. If another thread did modify the variable at the same time, the CAS operation will fail, but detect it and retry it in a while loop. The best thing about CAS is that it is implemented in hardware and is extremely efficient. If 100 threads execute this increment() method at the same time, in the worst case each thread will have to retry at most 99 times before the increment is complete. (By comparison, acquiring/releasing a lock can take thousands of instructions per thread.)
      

  12.   

    MESI protocol的wiki地址。
    http://en.wikipedia.org/wiki/MESI_protocol多核cpu进行计算时会缓存memory中某location的value,MESI protocol在此基础上在缓存的value后附加
    Modified Exclusive Shared Invalid 四个状态,不同的cpu的对memory中同一location的数据进行操作时,会被其他cpu捕获,并更新自己cache中缓存的该location的value的状态。通过这些状态减少了
    ----------
    value.compareAndSwap(oldValue,newValue)!=oldValue
    ----------
    CAS操作中获取memory中location的old value操作(即不用通过直接获取 memory 中的old value进行compare才能确认操作是同步的),从而达到优化,同时提供了高效并发的可能。