在java并发编程中,会遇到三个问题:
- 原子性
- 有序性
- 可见性
一、原子性
1)概念
原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
2)实例
对于操作:
++i
将它反编译成汇编代码:
mov ecx ,dword ptr [ebp - 4] ;把变量i的值送 ecx
add ecx,1
mov dword ptr [ebp - 4],ecx ;ecx加1后,赋值给i
在反编译成汇编可以看出顺序是先将i本身的值拿到寄存器ecx中,然会对寄存器自增,最后写回值。
借助java我可以通过看出如果内部不加阻塞,最后读出的结果是脏的。
/**
* 不共享数据count,每个线程自己维护自己的count
* @author 我们
*
*/
public class T1 extends Thread {
private int count = 0;
public T1(String name) {
super();
this.setName(name);
}
public void run() {
super.run();
while (count < 5) {
++count;
System.out.println("由" + this.currentThread().getName()
+ "计算.count=" + count);
}
}
public static void main(String[] args) {
T1 aMythread = new T1("A");
T1 bMythread = new T1("B");
T1 cMythread = new T1("C");
aMythread.start();
bMythread.start();
cMythread.start();
}
}
/*----output--------
由B计算.count=1
由A计算.count=1
由C计算.count=1
由C计算.count=2
由C计算.count=3
由C计算.count=4
由A计算.count=2
由B计算.count=2
由B计算.count=3
由B计算.count=4
由A计算.count=3
由C计算.count=5
由A计算.count=4
由A计算.count=5
由B计算.count=5
*/
如果我们想要它正常的执行,只需要在run前面加synchronized
二、有序性
1)概念
有序性:即程序执行的顺序按照代码的先后顺序执行。
2)实例
在开发并发程序的时候如果控制不好,程序的执行可能出现乱序的结果。
class OrderExample {
public int a = 0;
public boolean flag = false;
public void write() throws InterruptedException {
a = 1;![在这里插入图片描述](https://img-blog.csdnimg.cn/20191104144341904.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTQ0MzQ4Mw==,size_16,color_FFFFFF,t_70)
flag = true;
System.out.println("---write()---" + Thread.currentThread().getName());
}
public void reader() {
if (flag) {
int i = a + 1;
System.out.println("---reader()---i=" + i + " " + Thread.currentThread().getName());
}
}
}
class t1 extends Thread {
private OrderExample orderExample;
public t1(OrderExample orderExample) {
super();
this.orderExample = orderExample;
}
public void run() {
try {
orderExample.write();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class t2 extends Thread {
private OrderExample orderExample;
public t2(OrderExample orderExample) {
super();
this.orderExample = orderExample;
}
public void run() {
orderExample.reader();
}
}
public class Test4 {
public static void main(String[] args) throws InterruptedException {
OrderExample orderExample = new OrderExample();
t1 myT1 = new t1(orderExample);
t2 myT2 = new t2(orderExample);
myT1.start();
myT2.start();
}
}
/*------output-----
---write()---Thread-0
*/
程序的执行顺序可能未必和书写的顺序一致(可能对于现在的处理器该结果比较难模拟)
三、可见性
1)概念
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
2)实例
四、线程安全
1)概念
指某个函数、函数库在多线程环境中被调用时,能够正确地处理各个线程的局部变量,使程序功
能正确完成。
在java中采用阻塞的方式比较常见(synchronized),同时也可以采用关键字volatile来使变量在多个线程间可见。