解决线程的安全问题
上一篇博客线程安全问题
1.synchronized 关键字-监视器锁monitor lock
synchronized的底层是使用操作系统的mutex lock实现的。
- 当线程释放锁时,JMM会把该线程对应的工作内存中的共享变量刷新到主内存中;
- 当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量;
1.作为方法的修饰符——方法的定义前面
synchronized int add(int a,int b){...}
synchronized static int add(int a,int b){...}
2.作为同步代码块
synchronized(对象的引用){
......
}
3.代码演示
/**
* synchronized的语法使用示例
*/
public class ThreadDemo {
//同步方法
synchronized int add(int a,int b){
return 0;
}
synchronized static void sayHello(){
}
//同步代码块——能出现语句的地方
static void someMethod() {
Object object = new Object();
synchronized (object) {
}
}
}
2.用synchronized 解决上一篇博客中代码的线程安全问题
public class ThreadDemo2 {
private static int n = 0;
private static final int COUNT = 100000;
static class Adder extends Thread{
@Override
public void run() {
for (int i = 0;i < COUNT;i++){
synchronized (Adder.class){
n++;
}
}
}
}
static class Suber extends Thread{
@Override
public void run() {
for (int i = 0;i < COUNT;i++){
synchronized (Adder.class){//一定和上面的加同一把锁
n--;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Adder();
Thread t2 = new Suber();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(n);
}
}
3.volatile 关键字
修饰的共享变量,可以保证可见性,部分保证顺序性;
class ThreadDemo {
private volatile int n;
}