Java--JUC--八种锁
- 八种锁:
-
* 1.标准访问,两个访问之间是主线程sleep保证上面的线程先使用,先 调用send email,在发send msg
-
* 2.在发邮件的方法中暂停4秒钟,先send email再send email,线程A进入到sendEmail方法中,会将整个对象锁住,只能等到A线程释放锁B线程才可以使用
-
* 3.新增一个普通sayHello方法和同步锁无关,和send email及send msg没有关系,就像手机耳机一样,我是用的耳机,与系统内部功能之间的使用没有冲突
-
* 4.两个同步锁方法,2部手机,两个对象,不是同一把锁,两个线程不相争不会
-
* 5.2个静态同步方法,1部手机 静态同步方法锁的时整个类
-
* 6.2个静态同步方法,2部手机
-
* 7.1个静态同步方法,1个普通方法,1部手机,
-
* 8.1个静态同步方法,1个普通方法,2部手机
-
- 结论:
-
一个对象里面如果有多个synchronized方法,某一 个时刻内,只要- - 个线程去调用其中的一- 个synchronized方法了,
其它的线程都只能等待,换句话说,某-一个时刻内,只能有唯一一个线程去 访问这些synchronized方法 -
锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法
-
加个普通方法后发现和同步锁无关,包括静态同步锁,同步方法和静态同步方法也无关
-
换成两个对象后,不是同一把锁了,情况立刻变化。
-
synchronized实现同步的基础: Java中的每一个对 象都可以作为锁。
具体表现为以下3种形式:-
对个普通同步方法,锁是当前实例对象,锁的是当前对象this,(synchronized修饰的方法 )
-
对于同步方法块,锁是synchonized括 号里配置的对象。( synchronized(this){} )
-
对于静态同步方法,锁是当前类的Class对象。(static synchronized 同时修饰的方法)
-
-
当一个线程试图访间同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。
-
也就是说如果一个实例对 象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,
可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。 -
所有的静态同步方法用的也是同一把锁一类对象本身,
这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。
但是一旦- - 个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,
而不管是同一” 个实例对象的静态同步方法之间,.
还是不同的实例对象的静态同步方法之间,只要它们同一- 个类的实例对象! - 所有的静态同步锁是一把锁,不会影响普通的同步锁,也不会影响普通方法,
- 只有静态同步锁之间会相互影响,普通同步锁之间相互影响
- 普通的同步方法锁定是当前对象(this)的所有同步方法
- 静态的同步方法所得是所有对象的静态同步方法,也就是类(class)的所有静态同步方法
- 同一对象的所有的同步方法一把锁,所有的对象的(也就是整个类的)静态同步方法一把锁
-
- 代码实例:
-
package com.model.concurrent; import java.util.concurrent.TimeUnit; /**八种锁 * 1.标准访问,两个访问之间是主线程sleep保证上面的线程先使用,先 调用send email,在发send msg * 2.在发邮件的方法中暂停4秒钟,先send email再send email,线程A进入到sendEmail方法中,会将整个对象锁住,只能等到A线程释放锁B线程才可以使用 * 3.新增一个普通sayHello方法和同步锁无关,和send email及send msg没有关系,就像手机耳机一样,我是用的耳机,与系统内部功能之间的使用没有冲突 * 4.两个同步锁方法,2部手机,两个对象,不是同一把锁,两个线程不相争不会 * 5.2个静态同步方法,1部手机 静态同步方法锁的时整个类 * 6.2个静态同步方法,2部手机 * 7.1个静态同步方法,1个普通方法,1部手机, * 8.1个静态同步方法,1个普通方法,2部手机 * * * */ class Phone{ public static synchronized void sendEmail() throws InterruptedException { TimeUnit.SECONDS.sleep(4); System.out.println("************send email"); // synchronized (this){ 与上面synchronized修饰方法一样的效果 // TimeUnit.SECONDS.sleep(4); // System.out.println("************send email"); // } } public synchronized void sendMsg(){ System.out.println("************send msg"); } public void sayHello(){ System.out.println("************say hello"); } } public class LockDemo004 { public static void main(String[] args) throws InterruptedException { Phone phone=new Phone(); Phone phone1=new Phone(); new Thread(() ->{ try { phone.sendEmail(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start(); Thread.sleep(1000); new Thread(() ->{ // phone.sendMsg(); phone.sendMsg(); },"B").start(); new Thread(() ->{ phone.sayHello(); // phone1.sayHello(); },"input thread name").start(); } }
-