原子性
所谓的原子性是指在一次操作或者多次操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行,多个操作是一个不可以分割的整体。问题
static int money = 10;
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
while (money < 220000);
System.out.println("可以结婚了");
});
Thread thread2 = new Thread(() -> {
System.out.println("等五年后");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
money = 220000;
System.out.println("可以结婚了");
});
thread1.start();
thread2.start();
}
这里的问题是:线程1虽然知道结婚基金是十万,但是当money发生改变的时候,线程1无法知道最新的余额
volatile(不能保证原子性)解决
Volatile关键字 : 强制线程每次在使用的时候,都会看一下共享区域最新的值
当线程2修改了共享数据时,线程1没有及时获取到最新的值,如果还在使用原先的值,就会出现问题
1、堆内存是唯一的,每一个线程都有自己的线程栈
2、每一个线程在使用堆里面变量的时候,都会先拷贝一份到变量的副本中
3、在线程中,每一次使用是从变量的副本中获取
示例代码
volatile static int money = 10;
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
while (money < 220000);
System.out.println("可以结婚了");
});
Thread thread2 = new Thread(() -> {
System.out.println("等五年后");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
money = 220000;
System.out.println("可以结婚了");
});
thread1.start();
thread2.start();
}
** synchronized解决**
1、线程获得锁
2、清空变量副本
3、拷贝共享变量最新的值到变量副本中
4、执行代码
5、将修改后变量副本中的值赋值给共享数据
6、释放锁
示例代码
static int money = 10;
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
while (money < 220000);
synchronized ("") {
System.out.println("可以结婚了");
}
});
Thread thread2 = new Thread(() -> {
System.out.println("等五年后");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
money = 220000;
System.out.println("可以结婚了");
});
thread1.start();
thread2.start();
}
原子性_AtomicInteger
java从JDK1.5开始提供了java.util.concurrent.atomic包(简称Atomic包),这个包中的原子操作类提供了一种
用法简单,性能高效,线程安全地更新一个变量的方式
示例代码
public class Atom_ {
static AtomicInteger atomicInteger = new AtomicInteger(0);
public static void main(String[] args) {
List<Thread> list = new ArrayList<>();
for(int i = 1; i <= 10; i++){
Thread thread = new Thread(() -> {
for (int j = 0; j < 10000; j++) {
atomicInteger.incrementAndGet();
}
});
thread.start();
}
boolean[] arr = new boolean[list.size()];
a:while (true){
for (int i = 0; i < list.size(); i++) {
Thread.State state = list.get(i).getState();
if (state == Thread.State.TERMINATED){
arr[i] = true;
}
for (boolean b : arr) {
if (!b){
continue a;
}
}
}
break ;
}
}
}