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

我误解了volatile作用,大家能纠正一我吗?
Java code
public class TicketThread extends Thread {
   private volatile int i = 5;
   //我的理解是它是多个线程来共享它,不存在拷贝,修改以后必须马上写回。
   public void run(){
      while(i>0){ 
         i--;
         System.out.println(Thread.currentThread().getName()+"卖出车票,车票还剩 "+i+" 张");
         try {
            sleep(1000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }      
   }
   
   
   public static void main(String[] args) {
      TicketThread t1 = new TicketThread();
      TicketThread t2 = new TicketThread();
      t1.setName("1号窗口");
      t2.setName("2号窗口");
      t1.start();
      t2.start();      
   }
}


------解决方案--------------------
挥发变量.
volatile修饰符告诉编译器被volatile修饰的变量可以被程序的其他部分改变。
在多线程程序中,有时两个或更多的线程共享一个相同的实例变量。
一般的变量在多线程中是有copy的,每个线程一个copy.
volatile也不是很可靠
------解决方案--------------------
探讨
Java codepublicclass TicketThreadextends Thread {privatevolatileint i=5;//我的理解是它是多个线程来共享它,不存在拷贝,修改以后必须马上写回。publicvoid run(){while(i>0){
i--;
System.out.println(Thread.currentThread(?-

------解决方案--------------------
C里面也有,JAVA的什么意思我一直不明白,但是目前看来可能跟C的不一样。因为C中间插入汇编的话可能会修改某个变量,而由于编译器的优化,可能会忽略掉这个修改。要关闭这种所谓的优化,就需要对那个变量用violate申明
------解决方案--------------------
探讨
volatile,英文释义: 挥发性的,可变的,不稳定的。以我原来的理解是多线程共享到此变量时,必须强制写回程度,而不是从缓存中读取,这样保证这个字段的同步性。

      事实上不是这样的。在执行期间,编译好的代码出于效率原因会缓存字段值。由于可能有多条线程访问同一个字段,因此在读写字段、取值时不允许这里的缓存机制导致不一致性是很重要的。利用volatile修饰符可以告诉编译器,让它不要试图对本字段进行优化,因为这样会使得多条线程访问该字段时出现不可预测的结果。


这段话,我还是不能很好的理解。

------解决方案--------------------
volatile 保证 各线程间共享数据的一致性,和数据操作的原子性,不能保证线程间同步。 

能保证 i++ 的原子性,但是不能保证 i<0 i++ 和
System.out.println(Thread.currentThread().getName()+"卖出车票,车票还剩 "+i+" 张");

三个操作使用的是同一个 i。
楼主除了 volatile , 还要使用同步关键字。
------解决方案--------------------
加了volatile 表示是线程安全的。。。。
------解决方案--------------------
4
5楼 看看
------解决方案--------------------
冒似我的理解跟楼主的一样,运行下结果才知道不是那样的

关于write volatile和 read volatile 还有什么原子性,期待高手详细的解答,最好就是举例说下
------解决方案--------------------
我想了半天,把以前的代码拿出来看了又看,才发现了楼主一个重要的问题,所以达不到你的预期效果
并不是volatile用错了,而是你创建了两个单独的对象,两个单独的变量,怎么你也达不到共享的效果撒,

如果你要达到同步,应该在同一个对象在不同的线程中掉用才对你这样修改一下
 TicketThread t1 = new TicketThread();
 Thread t11=new Thread(t1,"1号窗口");
 Thread t22=new Thread(t1,"2号窗口");
t11.start();
t22.start();
这样就能够达到同步了


------解决方案--------------------
能够实现简单的同步
但是并不是保险