1. 并发编程的三个问题

1. 可见性

指一个线程对共享变量进行修改,另一个线程立即得到修改后的值

测试代码

public class Test01Visibility {
	private static boolean flag = true;

	public static void main(String[] args) throws InterruptedException {

		new Thread(() -> {
			while (flag) {
				//千万别打印,打印就没有效果
			}
		}).start();
		
		Thread.sleep(2000);
		
		new Thread(() -> {
			flag = false;
			System.out.println("线程修改了值为false");
		}).start();
	}
}

结果是值修改成了false了,但是程序还没结束进入死循环
在这里插入图片描述
线程2对共享变量进行了修改,但线程1却不知道。

2. 原子性

指一次或多次操作,要么所有操作执行成功并且不受其他因素干扰而停止,要么就是所有操作都不成功。

测试代码

public class Test02Atomicity {
	private static int number = 0;

	public static void main(String[] args) throws InterruptedException {
		
		List<Thread> list = new ArrayList<Thread>();
		
		for (int i = 0; i < 5; i++) {
			Thread t = new Thread(() -> {
				for (int j = 0; j < 1000; j++) {
					number++;
				}
			});
			t.start();
			list.add(t);
		}
		
		//免得主线程跑完了
		for (Thread thread : list) {
			thread.join();
		}
		
		System.out.println(number);
	}
}

最后运行有可能少于5000
在这里插入图片描述
这是因为number++;并不是一个原子性操作,通过javap -p -v反编译该class文件,可以看到其由4条指令构成
在这里插入图片描述
分别对应的大概意思是,(1)获取值,(2)准备常量1,(3)值+常量1,(4)把结果返回。
因此多个线程操作的时候,比如有可能线程1获取值的是100,正要准备100+1前,执行线程2了,此时线程2也获取到值100,也是100+1,最后线程1,和线程2都把101值返回到变量中。即做了两次加法但是结果只加了1.

3. 有序性

指程序中代码的执行顺序,java在编译和运行时会对代码进行优化,会导致最后程序的执行顺序不一定是我们编写代码的顺序

这个测试类有点难写,借用了一个jsrtress包

<dependency>
            <groupId>org.openjdk.jcstress</groupId>
            <artifactId>jcstress-core</artifactId>
            <version>0.7</version>
        </dependency>
package demo1;

import org.openjdk.jcstress.annotations.*;
import org.openjdk.jcstress.infra.results.I_Result;

@JCStressTest
@Outcome(id={"1","4"},expect = Expect.ACCEPTABLE,desc="ok")
@Outcome(id={"0"},expect = Expect.ACCEPTABLE_INTERESTING,desc="danger")
@State
public class Test03Ordering {


    int num = 0;
    boolean ready = false;

    @Actor
    public void actor1(I_Result r){
        if (ready) {
            r.r1 = num + num;
        } else {
            r.r1 = 1;
        }
    }

    @Actor
    public void actor2(I_Result r){
        num = 2;
        ready = true;
    }
}

大家可以自行百度一下怎么玩jcstress,这里就不多说了,只说结果,因为java对代码进行了优化,所以有可能 ready = true;会在 num = 2;前面折行,得到了一个顺序执行时不可能出现的结果(结果为0).

博主的坚持 离不开大家关注、评论和点赞,感谢大家支持。护发路上互相扶持!!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值