Java 在不同步的情况下使用volatile
知道 读写是针对所有声明为volatile的变量的 问题1:这是否可以理解为Java 在不同步的情况下使用volatile,java,volatile,Java,Volatile,知道 读写是针对所有声明为volatile的变量的 问题1:这是否可以理解为 private volatile int x = 0; x++操作是原子的 那 标记变量volatile并不能消除同步的所有需要 原子行动,因为 问题2:我想知道在什么情况下(如果有的话),可以看到标记为volatile的变量,而看不到标记为synchronized的块的任何方法(尝试访问/修改变量) 换言之,所有需要防止并发修改的变量是否应标记为volatile x++;操作是原子的 否。这将减少到x=x+1。对x
private volatile int x = 0;
x++代码>操作是原子的
那
标记变量volatile并不能消除同步的所有需要
原子行动,因为
问题2:我想知道在什么情况下(如果有的话),可以看到标记为volatile
的变量,而看不到标记为synchronized的块的任何方法(尝试访问/修改变量)
换言之,所有需要防止并发修改的变量是否应标记为volatile
x++;操作是原子的
否。这将减少到x=x+1
。对x
的读取是原子的,对x
的写入是原子的,但是x=x+1
作为一个整体不是原子的
我想知道在什么情况下(如果有的话),可以看到标记为volatile的变量,而看不到标记为synchronized的块的任何方法(尝试访问/修改变量)
嗯,有各种并发方法都不使用synchronized
。Java中还有各种各样的其他锁定实用程序,无锁算法仍然需要像volatile
这样的东西:ConcurrentLinkedQueue
是一个具体的例子,尽管它广泛使用了“magic”compareAndSet
原子。否同步(尽管可以从volatile-开始构建同步块)
因此,不,它对x++
没有帮助-这仍然是一种读写操作,需要某种形式的同步
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,则可能看不到更新 作为一个可快速测试的示例,可以说明前面的答案,这始终会产生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();
}
}
}
}
导入java.util.concurrent.AtomicInteger;
公共类线程测试\u同步{
公共静态void main(字符串[]args){
ThreadTest_synchronize tt=新的ThreadTest_synchronize();
试一试{
tt.go();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
private void go()引发InterruptedException{
MyRunnable t=新的MyRunnable();
线程myThread_1=新线程(t,“t1”);
螺纹myThread_2=新螺纹(t,“t2”);
myThread_1.start();
myThread_2.start();
myThread_1.join();
myThread_2.join();
System.out.println(“Processing count=“+t.getCount());
}
私有类MyRunnable实现Runnable{
私有AtomicInteger计数=新的AtomicInteger(0);
@凌驾
公开募捐{
对于(int i=1;i<5;i++){
剂量测定法(i);
计数。getandad(1);
}
}
公共原子整数getCount(){
返回这个.count;
}
私人无效剂量测定(int i){
试一试{
睡眠(i*300);
}捕捉(中断异常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();
}
}
}
}
公共类ThreadTest\u volatile{
公共静态void main(字符串[]args){
ThreadTest_volatile tt=新的ThreadTest_volatile();
试一试{
tt.go();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
private void go()引发InterruptedException{
MyRunnable t=新的MyRunnable();
线程myThread_1=新线程(t,“t1”);
螺纹myThread_2=新螺纹(t,“t2”);
myThread_1.start();
myThread_2.start();
myThread_1.join();
myThread_2.join();
System.out.println(“Processing count=“+t.getCount());
}
私有类MyRunnable实现Runnable{
私有易失性整数计数=0;
@凌驾
公开募捐{
对于(int i=1;i<5;i++){
剂量测定法(i);
计数++;
}
}
专用整数相加(整数计数){
返回++计数;
}
public int getCount(){
返回计数;
}
私人无效剂量测定(int i){
试一试{
睡眠(i*300);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}
极好的答案和示例。非常感谢。