Synchronized作用:
官方:同步方法支持一种简单的策略来方式线程干扰和内存一致性错误,如果一个对象对多个线程可见,则对该对象变量所有的读取和写入都是同步方法完成的。
通俗:能够保证同一时刻最多只有一个线程执行改代码,以保证并发安全效果。
Synchronized地位:
关键字,是基本的同步互斥手段,并发编程必学内容。
不用并发的后果:
多线程情况下出现结果跟预期不符,我们称作线程不安全,例如下面结果不是我们想要的20000
public class DisAppearRequest1 implements Runnable{ static int i = 0; static DisAppearRequest1 instance = new DisAppearRequest1(); public static void main(String[] args) throws Exception{ Thread thread1 = new Thread(instance); Thread thread2 = new Thread(instance); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(i); } public void run() { for(int j=0;j<10000;j++){ i++; } } }
count++ ;它看上去只是一个操作,实际上包含了三个动作:
- 读取 count。
- 将 count 加1。
- 将 count的值写入到内存中。假设count为1,线程A进入该方法进行加1操作后count变成2,还未写入内存。线程B进入该方法 对读取的count依旧为1,进行加1后count也是2,因此无论是A还是B写入内存的数值都是2,预期中本来应该为3的数值变成了2
用法介绍
对象锁:包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)
类锁:指synchronized修饰静态的方法或指定锁为Class对象。
几种情况:
- 两个线程同时访问同一个对象(同一个instance)的同步方法(Synchronized修饰),顺序执行,线程一执行结束,线程2执行,是对象锁的方法锁
- 两个对象访问的是两个对象(两个实例)的同步方法,同步不起作用,相当于两个锁,每个实例有自己的锁,所以两个线程会是同时开始同时结束
- 两个线程访问的是synchronized的静态方法,顺序执行,是类锁的static synchronized
- 同时访问同步方法和非同步方法(一个被sychronized,一个没有),(线程是同一实例,线程一访问同步线程2访问非同步) , 两个线程同时执行,因为同步方法对非同步方法不会有任何影响
- 访问同一个对象的不同的普通同步方法,因为是同一个对象,不同的同步方法默认都是this即当前的实例,所以存在线程等待释放,所以会是同步,是对象锁的同步方法 方法锁
- 同时访问static synchronized 和非静态synchronized ,线程同时执行,他们所指定的锁对象是不一样的(没有加static的锁是this实例本身,加了static时锁是类锁,他背后的锁是.class对象)
- 如果同时访问同步方法中包含了非同步方法,我觉得是同步的,因为入口同步方法不是放资源,也不能进入非同步方法,代码执行也是线程安全的 , (((但是老师解释一旦进入非同步方法就灭有锁了))
方法抛出异常后会释放锁吗(一旦抛出异常,第二个线程立即获得锁,立刻进入同步方法,意味着锁已经释放):不需要我们主动去释放锁,抛出异常后jvm释放了锁。
这些信息都是从慕课网上听来的