8锁现象 彻底理解锁
作者:互联网
问题1
下面代码的执行顺序?
package com.jie.lock8;
import java.util.concurrent.TimeUnit;
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("打电话");
}
}
答案:必是发短信先执行
原因:synchronized本质锁的对象是方法的调用者,打电话和发短信去代码里都是由phone对象去调用 即同一个对象
因此两个方法用的是同一个锁 由于主函数sleep了一秒 所以是A先拿到锁 B必须等A执行完才能执行
问题2
package com.jie.lock8;
import java.util.concurrent.TimeUnit;
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(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
答案:仍然是先发短信 原因同上 就算A在sleep也仍然持有着锁
问题3 吧下面的方法改为非syn方法 执行顺序是?
package com.jie.lock8;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
Phone2 phone2=new Phone2();
new Thread(()->{phone2.sendSms();},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{phone2.hello();},"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("打电话");
}
public void hello(){
System.out.println("hello");
}
}
答案:先Hello 原因也很简单 不用想复杂了 hello没加锁不受影响
问题4
现在我们使用两个对象 执行顺序是?
package com.jie.lock8;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
Phone2 phone=new Phone2();
Phone2 phone2=new Phone2();
new Thread(()->{phone.sendSms();},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{phone2.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("打电话");
}
public void hello(){
System.out.println("hello");
}
}
答案:打电话先
原因很简单 锁的本质是对象的调用者 两个同步方法调用者是不同的对象 不存在互锁的情况
问题5-6 改为静态方法
问题5体现不出静态的特点直接掠过(单个对象调用两个静态同步 问执行顺序)
将方法改为静态方法 那么执行顺序是?
package com.jie.lock8;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
Phone2 phone=new Phone2();
Phone2 phone2=new Phone2();
new Thread(()->{phone.sendSms();},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{phone2.call();},"B").start();
}
}
class Phone2{
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("打电话");
}
}
答案:与使用非静态方法的结果不一样 先发短信后打电话 原因在于静态方法本质锁的就是类本身,与你的对象无关。
问题7 梦魇融合怪
现在一个静态方法 一个正常方法 执行顺序?
package com.jie.lock8;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
Phone2 phone=new Phone2();
//Phone2 phone2=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 static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
很明显是打电话先 因为两者锁的不一样 一个锁的是Class类模板 一个是类对象
问题8 看完你就是锁王
package com.jie.lock8;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) {
Phone2 phone=new Phone2();
Phone2 phone2=new Phone2();
new Thread(()->{phone.sendSms();},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{phone2.call();},"B").start();
}
}
class Phone2{
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("打电话");
}
}
还是打电话先! 道理就不说了 别搞整晕了 上面原理懂了 肯定懂
标签:彻底,Phone2,void,理解,TimeUnit,println,new,现象,public 来源: https://www.cnblogs.com/OfflineBoy/p/15244567.html