深度剖析线程安全性问题与底层(一)
线程安全的三个问题: 原子性 可见性 有序性
原子性:不能拆
可见性:当一个线程对共享变量进行修改后,其他线程能够立即看到修改后的值
有序性: 有重排序问题,单线程下重排序后结果不变,多线程情况下会出现问题
如何保证原子性
1.synchronized关键字
2.Atomic类
Synchronize的三种使用方式
同步代码块
同步方法
修饰一个静态方法
public class Executor {
Object lock = new Object();
public void method1(){
synchronized (lock){
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 5; i++) {
System.out.println("Thread "+threadName+" 正在执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
// public synchronized static void method2(){
// String threadName = Thread.currentThread().getName();
// for (int i = 0; i < 5; i++) {
// System.out.println("Thread "+threadName+" 正在执行");
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
// }
// }
}
使用wait和notify实现生产者消费者关系
不能在没有拿到锁的情况下使用两个方法(会报错)
wait方法会释放锁
Consumer
public class Consumer extends Thread{
@Override
public void run() {
while (true) {
synchronized (Desk.lock) {
// true 代表桌上有食物
if (Desk.flag) {
System.out.println("消费者正在取餐");
Desk.flag = false;
//Desk.lock.notifyAll();
} else {
// false 代表桌上没有食物,消费者需要等待
try {
// 把 notifyAll() 写在这里
Desk.lock.notifyAll();
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
public class Producer extends Thread{
@Override
public void run() {
while (true) {
synchronized (Desk.lock) {
if (Desk.flag) {
try {
// notifyAll() 写在这里
Desk.lock.notifyAll();
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
System.out.println("通知消费者吃饭");
Desk.flag = true;
// Desk.lock.notifyAll();
}
}
}
}
}
public class Desk {
public static boolean flag = false;
public static Object lock = new Object();
}
}
}
}
```java
public class Desk {
public static boolean flag = false;
public static Object lock = new Object();
}
(公共锁)