JUC学习笔记——共享模型之管程( 三 )


/*第1题*/ @Slf4j(topic = "c.Number")class Number{public synchronized void a() {log.debug("1");}public synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();}// 结果:1,2或2,1// 解析:两者都绑定n1对象锁,互斥关系/*第2题*/ @Slf4j(topic = "c.Number")class Number{public synchronized void a() {sleep(1);log.debug("1");}public synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();}// 结果:1s后1,2或2,1s后1// 解析:两者都绑定n1对象锁,互斥关系;sleep不具有任何关系/*第3题*/ @Slf4j(topic = "c.Number")class Number{public synchronized void a() {sleep(1);log.debug("1");}public synchronized void b() {log.debug("2");}public void c() {log.debug("3");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();new Thread(()->{ n1.c(); }).start();}// 结果:3 1s 12 或 23 1s 1 或 32 1s 1// 解析:a,b都是n1对象锁,c不具有锁/*第4题*/ @Slf4j(topic = "c.Number")class Number{public synchronized void a() {sleep(1);log.debug("1");}public synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();Number n2 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n2.b(); }).start();}// 结果:2 1s 后 1// 解析:a是n1的对象锁,b是n2的对象锁,不具有互斥关系/*第5题*/ @Slf4j(topic = "c.Number")class Number{public static synchronized void a() {sleep(1);log.debug("1");}public synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();}// 结果:2 1s 后 1// 解析:a采用类锁,b采用n1对象锁,不具有互斥关系/*第6题*/ @Slf4j(topic = "c.Number")class Number{public static synchronized void a() {sleep(1);log.debug("1");}public static synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n1.b(); }).start();}// 结果:1s 后12, 或 2 1s后 1// 解析:两者都是类锁,具有互斥关系/*第7题*/ @Slf4j(topic = "c.Number")class Number{public static synchronized void a() {sleep(1);log.debug("1");}public synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();Number n2 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n2.b(); }).start();}// 结果:2 1s 后 1// 解析:a采用类锁,b采用n2对象锁,不具有互斥关系/*第8题*/ @Slf4j(topic = "c.Number")class Number{public static synchronized void a() {sleep(1);log.debug("1");}public static synchronized void b() {log.debug("2");}}public static void main(String[] args) {Number n1 = new Number();Number n2 = new Number();new Thread(()->{ n1.a(); }).start();new Thread(()->{ n2.b(); }).start();}// 结果:1s 后12, 或 2 1s后 1// 解析:两者都是类锁,具有互斥关系线程安全分析这小节我们将会介绍线程安全分析
变量线程安全问题首先我们来思考成员变量和静态变量的安全性:

  • 如果它们没有共享,则线程安全
  • 如果它们被共享了:如果只有读操作,则线程安全
  • 如果它们被共享了:如果有读写操作,则这段代码是临界区,需要考虑线程安全
我们再来思索一下局部变量的安全性:
  • 局部变量是线程安全的
  • 局部变量引用的对象:如果该对象没有逃离方法的作用访问,它是线程安全的
  • 局部变量引用的对象:如果该对象逃离方法的作用范围,需要考虑线程安全
我们通过简单代码进行测试:

经验总结扩展阅读