package lock8; import java.util.concurrent.TimeUnit; /** * 8锁 就是关于锁的8个问题 * 1.标准情况下,两个线程先打印 发短信还是打电话? ->发短信 原因 A先执行 A先拿到锁, */ public class Test1 { public static void main(String[] args) { Phone phone = new Phone(); new Thread(()->{ phone.sendSms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(()->{ phone.call(); },"B").start(); } } class Phone{ public synchronized void sendSms(){ System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } }
package lock8; import java.util.concurrent.TimeUnit; /** * 答案 发短信 原因: synchronized 锁住了 Phone2实例化的对象, 只有当短信执行完以后 锁才会被释放 */ public class Test2 { public static void main(String[] args) { Phone2 phone = new Phone2(); new Thread(()->{ phone.sendSms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(()->{ phone.call(); },"B").start(); } } class Phone2{ public synchronized void sendSms(){ try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } }
package lock8; import java.util.concurrent.TimeUnit; /** * 增加了一个普通方法后,先执行 hello 还是发短信。 执行的是 hello 原因,hello没有锁,不是同步方法,不受锁的影响 */ public class Test3 { public static void main(String[] args) { Phone3 phone = new Phone3(); new Thread(()->{ phone.sendSms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(()->{ phone.hello(); },"B").start(); } } class Phone3{ public synchronized void sendSms(){ try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } //这里没有锁,不是同步方法,不受锁的影响 public void hello(){ System.out.println("hello"); } }
package lock8; import java.util.concurrent.TimeUnit; /** * 执行结果:打电话 原因:一个对象 只有一把锁。 phone1的锁 不影响phone2的锁 。 */ public class Test4 { public static void main(String[] args) { Phone4 phone1 = new Phone4(); Phone4 phone2 = new Phone4(); new Thread(()->{ phone1.sendSms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(()->{ phone2.call(); },"B").start(); } } class Phone4{ public synchronized void sendSms(){ try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public synchronized void call(){ System.out.println("打电话"); } }
package lock8; import java.util.concurrent.TimeUnit; /** * 执行结果:发短信 原因 :锁的是phone5这个class。 */ public class Test5 { public static void main(String[] args) { Phone5 phone = new Phone5(); new Thread(()->{ phone.sendSms(); },"A").start(); new Thread(()->{ phone.call(); },"B").start(); } } class Phone5{ //static 静态方法 类一加载就有了,锁的是class //Class<Phone5> phone5Class = Phone5.class; public static synchronized void sendSms(){ try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public static synchronized void call(){ System.out.println("打电话"); } }
package lock8; import java.util.concurrent.TimeUnit; /** * 执行结果:发短信 原因 :锁的是phone5这个class。 */ public class Test6 { public static void main(String[] args) { //两个对象的Class类模板 只有一个,static,锁的是class。 //疑问,可以看到static修饰的只是Phone6类里面的具体的方法。 跟Class类模板有关系吗? Phone6 phone1 = new Phone6(); Phone6 phone2 = new Phone6(); new Thread(()->{ phone1.sendSms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(()->{ phone2.call(); },"B").start(); } } class Phone6{ //static 静态方法 类一加载就有了,锁的是class //Class<Phone5> phone5Class = Phone5.class; public static synchronized void sendSms(){ try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } public static synchronized void call(){ System.out.println("打电话"); } }
package lock8; import java.util.concurrent.TimeUnit; /** * 执行结果:打电话 原因 :锁的是phone5这个class。 */ public class Test7 { public static void main(String[] args) { //两个对象的Class类模板 只有一个,static,锁的是class。 //疑问,可以看到static修饰的只是Phone6类里面的具体的方法。 跟Class类模板有关系吗? Phone7 phone = new Phone7(); new Thread(()->{ phone.sendSms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(()->{ phone.call(); },"B").start(); } } class Phone7{ //static 静态方法 类一加载就有了,锁的是class //static 修饰的方法 锁的是class模板。 一个类里 所有的方法 被static修饰过以后 锁的都是class模板 public static synchronized void sendSms(){ try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } //普通的同步方法 public synchronized void call(){ System.out.println("打电话"); } }
package lock8; import java.util.concurrent.TimeUnit; /** * 执行结果:打电话 原因 :static 修饰的方法 锁的是class模板。 一个类里 所有的方法 被static修饰过以后 锁的都是class模板 */ public class Test8 { public static void main(String[] args) { //两个对象的Class类模板 只有一个,static,锁的是class。 //疑问,可以看到static修饰的只是Phone6类里面的具体的方法。 跟Class类模板有关系吗? Phone8 phone1 = new Phone8(); Phone8 phone2 = new Phone8(); new Thread(()->{ phone1.sendSms(); },"A").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(()->{ phone2.call(); },"B").start(); } } class Phone8{ //static 静态方法 类一加载就有了,锁的是class //static 修饰的方法 锁的是class模板。 一个类里 所有的方法 被static修饰过以后 锁的都是class模板 public static synchronized void sendSms(){ try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("发短信"); } //普通的同步方法 public synchronized void call(){ System.out.println("打电话"); } }
总结: 什么是锁 , 永远记住一句话, synchronized 锁 锁的永远都是对象, 一个对象只可能有一把锁。
如果一个类某一个方法 用static+synchronized 修饰了。 那么 该类 所有同样被 static+synchronized 修饰的方法 锁的都是类的模板。
synchronized