使用volatile而不同步

知道

对于声明为volatile的所有变量,读取和写入都是primefaces的

问题1:这可以理解为

private volatile int x = 0; 

x++; 操作是primefaces的?

然后

标记变量volatile不会消除同步primefaces操作的所有需要​​,因为仍然可能存在内存一致性错误。

问题2:我想知道在什么情况下(如果有的话)可以看到标记为volatile的变量并且看不到任何标记为synchronized的块的方法(试图访问/修改变量)?

换句话说,是否应将所有需要保护以防止并发修改的变量标记为volatile

volatile只为你提供额外的可见性保证,long / double的primefaces写入/读取(否则不能由JLS保证,是)和一些内存顺序保证。 没有同步(虽然可以构建以volatile开头的同步块 – Dekker的算法 )所以不,它对x++没有帮助 – 它仍然是读取,包含和写入,需要某种forms的同步。

volatile的一个例子是着名的双重检查锁定,我们大部分时间都避免同步,因为排序保证是我们所需要的:

 private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) { helper = new Helper(); } } } return helper; } 

一个绝对没有涉及同步的例子是一个简单的退出标志,这里不是关于订购保证而是关于保证的可见性

 public volatile boolean exit = false; public void run() { while (!exit) doStuff(); // exit when exit set to true } 

如果另一个线程设置exit = true那么执行while循环的另一个线程将保证看到更新 – 没有volatile,它可能不会。

X ++; 操作是primefaces的?

不。这减少到x = x + 1x的读取是primefaces的,对x的写入是primefaces的,但x = x + 1整体上不是primefaces的。

我想知道在什么情况下(如果有的话)可以看到标记为volatile的变量并且看不到任何标记为synchronized的块的方法(尝试访问/修改变量)?

好吧,有各种不使用synchronized并发方法。 Java中有各种各样的其他锁定实用程序,而且无锁算法仍然需要像volatile这样的东西: ConcurrentLinkedQueue是一个特定的例子,尽管它广泛使用了“神奇的” compareAndSetprimefaces。

作为一个快速可测试的示例,可以说明以前的答案,这总是最终计数为8:

 import java.util.concurrent.atomic.AtomicInteger; public class ThreadTest_synchronize { public static void main(String[] args) { ThreadTest_synchronize tt = new ThreadTest_synchronize (); try { tt.go(); } catch (InterruptedException e) { e.printStackTrace(); } } private void go() throws InterruptedException{ MyRunnable t = new MyRunnable(); Thread myThread_1 = new Thread( t, "t1"); Thread myThread_2 = new Thread( t, "t2"); myThread_1.start(); myThread_2.start(); myThread_1.join(); myThread_2.join(); System.out.println("Processing count="+t.getCount()); } private class MyRunnable implements Runnable{ private AtomicInteger count=new AtomicInteger(0); @Override public void run() { for(int i=1; i< 5; i++){ doSomething(i); count.getAndAdd(1); } } public AtomicInteger getCount() { return this.count; } private void doSomething(int i) { try { Thread.sleep(i*300); } catch (InterruptedException e) { e.printStackTrace(); } } } } 

虽然这通常不会:

 public class ThreadTest_volatile { public static void main(String[] args) { ThreadTest_volatile tt = new ThreadTest_volatile (); try { tt.go(); } catch (InterruptedException e) { e.printStackTrace(); } } private void go() throws InterruptedException{ MyRunnable t = new MyRunnable(); Thread myThread_1 = new Thread( t, "t1"); Thread myThread_2 = new Thread( t, "t2"); myThread_1.start(); myThread_2.start(); myThread_1.join(); myThread_2.join(); System.out.println("Processing count="+t.getCount()); } private class MyRunnable implements Runnable{ private volatile int count = 0; @Override public void run() { for(int i=1; i< 5; i++){ doSomething(i); count++; } } private int add(int count){ return ++count; } public int getCount(){ return count; } private void doSomething(int i) { try { Thread.sleep(i*300); } catch (InterruptedException e) { e.printStackTrace(); } } } }