synchronized
Posted 无赖H4
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了synchronized相关的知识,希望对你有一定的参考价值。
synchronized 关键字-监视器锁monitor lock
synchronized 是一种保护线程安全的机制。
synchronized语法
- 修饰任意的方法——方法修饰关键字
- 普通方法
synchronized void m2() {}
- 静态方法
static synchronized void m3() {}
- 同步代码块——可能出现在语句的位置(方法中,构造代码块中,静态代码块)
Object o = new Object();
synchronized(o/*任意类型的引用*/){
//语句
}
预备知识
Class 是描述 类(Class)的类。
描述一个类的类,有且仅有一个。
例如:
Person p = new Person();
Class c1 = p.getClass();
Class c2 = Person.class;
c1 == c2 是true,引用指的是同一个对象;
Java中的对象中,有哪些数据:
任意的Java中的对象,都内含一把锁,这把锁被称为 同步锁/监视器锁
另外还包括Class对象
synchronized关键字的作用
以同步代码块为例:
这个引用不可以是null,否则会有NPE
注意:
synchronized修饰普通方法,视为对this加锁
synchronized修饰静态方法,视为对XX.class加锁
两个线程互斥
线程之间如何因为 锁 发生争抢——两个线程互斥
例如:
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
class MyThread extends Thread {
@Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程:语句1");
synchronized (SyncDemo2.o) {
System.out.println("子线程: 语句2");
}
System.out.println("子线程: 语句3");
}
}
public class SyncDemo2 {
public static Object o;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
MyThread t = new MyThread();
t.start();
synchronized (o) {
System.out.println("主线程:等待输入");
scanner.nextLine();
System.out.println("主线程: 马上释放锁");
}
}
}
只有前一个释放锁后,另外一个线程才能加锁开始执行(互斥)
例子:
void m1() {}
synchronized void m2() {}
static synchronized void m3() {}
void m4() {
synchronized (this) {}
}
static void m5() {
synchronized (SyncDemo4.class) {}
}
void m6() {
synchronized (SyncDemo4.class) {}
}
void m7() {
synchronized (getClass()) {}
}
上面的例子也体现了:
synchronized修饰普通方法,视为对this加锁
synchronized修饰静态方法,视为对XX.class加锁
两个线程要出现互斥:
1、两个线程都有加锁操作
2、两个线程加的是同一把锁
synchronized 加锁的过程
- 根据引用找到对象,加锁
- 加锁成功,直接向下执行
- 加锁失败
1、把自己的对象放到这把锁的阻塞队列中
2、把状态变更为一种阻塞状态(BLOCKED)——专为同步锁加锁失败设计
3、主动放弃CPU
synchronized 释放锁的过程
1、释放锁
2、把这把锁的阻塞队列中等待的线程们,状态改为就绪(一个或多个,释放那个)
synchronized容易被忽视的地方
当加锁后,上下两个语句间的间隔不确定(不知道何时释放锁)
synchronized的作用
- 保护原子性 (需要保证互斥)
- 内存可见性一直
1、一旦加锁成功,必须从主存储中,将最新的数据同步到工作存储中——保证线程看到的最新数据
2、释放锁的时候,必须做一次把工作存储的数据刷会主存储的操作(保证主存储中是最新的数据) - 代码重排序
1、会一定程度上保持代码重排序
以上是关于synchronized的主要内容,如果未能解决你的问题,请参考以下文章