写在前面: 虽然平时自己有做笔记的习惯,但都保存在本地。但随着笔记量的增多,自己打开笔记的习惯渐渐消失了。所以试试博客,一是好找笔记,二是能相互交流。一举两得。感谢关注我博客的朋友,这会督促我不断的学习、进步。高并发这块是观看马士兵老师的教程做的随堂笔记。感谢马老师!
注意:共享资源读写的时候才涉及到线程同步。
多线程同步:即限制某个资源在同一时刻只能被一个线程访问。
1.1 第1种写法(o)
/**
* synchronized关键字
* 对某个对象加锁
* @author mashibing
*/
package yxxy.c_001;
public class T {
private int count = 10;
private Object o = new Object();
public void m() {
synchronized(o) { //任何线程要执行下面的代码,必须先拿到o的锁
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
}
解说: 要执行这段代码,先去执行这个对象的锁。 注意:这个对象锁画出来的堆内存new出来的对象,而不是引用 也就是说在真正申请锁的时候,这个锁的信息是记录在堆内存对象中。 如果o要是指向别的对象,你这个锁的对象就变了。 只要有一个线程拿到锁,其他线程就拿不到锁。—> 这称为互斥锁。
也就是把o给锁定了!
1.2 第2种写法(this)
刚才这把锁是我们自己new出来的,但是这样每次new一个不干别的,专门当锁的对象实在是太麻烦了。 以下为简便写法: new 一个T出来,指向自身。把自身的对象锁定。【锁定自身再执行代码】
注意:synchronized锁定的是一个对象,而不是代码块。
/**
* synchronized关键字
* 对某个对象加锁
* [@author](https://my.oschina.net/arthor) mashibing
*/
package yxxy.c_002;
public class T {
private int count = 10;
public void m() {
synchronized(this) { //任何线程要执行下面的代码,必须先拿到this的锁
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
}
1.3 第3种写法(写在方法声明上)
如果一段代码在开始的时候就要synchronized(this)。到结束的时候才释放这把锁。那有一个简便的写法。
直接写在方法的声明上:
package yxxy.c_003;
public class T {
private int count = 10;
public synchronized void m() { //等同于在方法的代码执行时要synchronized(this)
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
1.4 synchronized 用在静态方法上
相当于锁定的是T.class【锁定的是当前Class类对象】
/**
* synchronized关键字
* 对某个对象加锁
* @author mashibing
*/
package yxxy.c_004;
public class T {
private static int count = 10;
public synchronized static void m() { //这里等同于synchronized(yxxy.c_004.T.class)
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
//相当于是下面这种写法
public static void mm() {
synchronized(T.class) { //考虑一下这里写synchronized(this)是否可以?
//t.class 是Class里面的对象 [反射知识]
count --;
}
}
}
由于静态的时候是没有this可以锁定,静态的属性和方法是不需要new对象来访问的。所以就没有this引用的存在。
1.5 分析程序的输出
发现问题: 5个线程访问的count都是同一个。
在没打印之前另外2个线程又减了2下。所以变成7了。
这就是线程同步的问题。 加锁即可解决。
总结:synchronized 是原子操作,不可分