最初资源类
class Phone //资源类
{
public synchronized void sendEmail()
{
System.out.println("-----sendEmail");
}
public synchronized void sendSMS()
{
System.out.println("-----sendSMS");
}
}
题目
/** * 题目:谈谈你对多线程锁的理解,8锁案例说明 * 口诀:线程 操作 资源类 * 8锁案例说明: * 1 标准访问有ab两个线程,请问先打印邮件还是短信 * 2 sendEmail方法中加入暂停3秒钟,请问先打印邮件还是短信 * 3 添加一个普通的hello方法,请问先打印邮件还是hello * 4 有两部手机,请问先打印邮件还是短信 * 5 有两个静态同步方法,有1部手机,请问先打印邮件还是短信 * 6 有两个静态同步方法,有2部手机,请问先打印邮件还是短信 * 7 有1个静态同步方法,有1个普通同步方法,有1部手机,请问先打印邮件还是短信 * 8 有1个静态同步方法,有1个普通同步方法,有2部手机,请问先打印邮件还是短信**/
第一题
1 标准访问有ab两个线程,请问先打印邮件还是短信
资源类
class Phone //资源类
{
public synchronized void sendEmail()
{
System.out.println("-----sendEmail");
}
public synchronized void sendSMS()
{
System.out.println("-----sendSMS");
}
}
测试
public class Lock8Demo
{
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
new Thread(() -> {
phone.sendEmail();
},"a").start();
//暂停毫秒,保证a线程先启动
try { TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
phone.sendSMS();
},"b").start();
}
}
结果
-----sendEmail
-----sendSMS
第二题
2 sendEmail方法中加入暂停3秒钟,请问先打印邮件还是短信
资源类
class Phone //资源类
{
public synchronized void sendEmail()
{
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("-----sendEmail");
}
public synchronized void sendSMS()
{
System.out.println("-----sendSMS");
}
}
测试
public class Lock8Demo
{
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
new Thread(() -> {
phone.sendEmail();
},"a").start();
//暂停毫秒,保证a线程先启动
try { TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
phone.sendSMS();
},"b").start();
}
}
结果
-----sendEmail
-----sendSMS
第三题
3 添加一个普通的hello方法,请问先打印邮件还是hello
资源类
class Phone //资源类
{
public synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public void hello() {
System.out.println("-----hello");
}
}
测试
public class Lock8Demo
{
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
new Thread(() -> {
phone.sendEmail();
},"a").start();
//暂停毫秒,保证a线程先启动
try { TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
phone.hello();
},"b").start();
}
}
结果
-----hello
-----sendEmai
第四题
4 有两部手机,请问先打印邮件还是短信
资源类
class Phone //资源类
{
public synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public synchronized void sendSMS() {
System.out.println("-----sendSMS");
}
}
测试
public class Lock8Demo {
public static void main(String[] args)//一切程序的入口
{
// 第一个手机
Phone phone = new Phone();
// 第二个手机
Phone phone2 = new Phone();
new Thread(() -> {
phone.sendEmail();
}, "a").start();
//暂停毫秒,保证a线程先启动
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone2.sendSMS();
}, "b").start();
}
}
结果
-----sendSMS
-----sendEmail
第五题
5 有两个静态同步方法,有1部手机,请问先打印邮件还是短信
资源类
class Phone //资源类
{
public static synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public static synchronized void sendSMS() {
System.out.println("-----sendSMS");
}
}
测试
public class Lock8Demo {
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
new Thread(() -> {
phone.sendEmail();
}, "a").start();
//暂停毫秒,保证a线程先启动
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone.sendSMS();
}, "b").start();
}
}
结果
-----sendEmail
-----sendSMS
第六题
6 有两个静态同步方法,有2部手机,请问先打印邮件还是短信
资源类
class Phone //资源类
{
public static synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public static synchronized void sendSMS() {
System.out.println("-----sendSMS");
}
}
测试
public class Lock8Demo {
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(() -> {
phone.sendEmail();
}, "a").start();
//暂停毫秒,保证a线程先启动
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone2.sendSMS();
}, "b").start();
}
}
结果
-----sendEmail
-----sendSMS
第七题
7 有1个静态同步方法,有1个普通同步方法,有1部手机,请问先打印邮件还是短信
资源类
class Phone //资源类
{
public static synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public synchronized void sendSMS() {
System.out.println("-----sendSMS");
}
}
测试
public class Lock8Demo {
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
new Thread(() -> {
phone.sendEmail();
}, "a").start();
//暂停毫秒,保证a线程先启动
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone.sendSMS();
}, "b").start();
}
}
结果
-----sendSMS
-----sendEmail
第八题
8 有1个静态同步方法,有1个普通同步方法,有2部手机,请问先打印邮件还是短信
资源类
class Phone //资源类
{
public static synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public synchronized void sendSMS() {
System.out.println("-----sendSMS");
}
}
测试
public class Lock8Demo {
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(() -> {
phone.sendEmail();
}, "a").start();
//暂停毫秒,保证a线程先启动
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone2.sendSMS();
}, "b").start();
}
}
结果
-----sendSMS
-----sendEmail
其余问题
9 有1个静态同步方法,有1个普通方法,有1部手机,请问先打印邮件还是hello
资源类
class Phone //资源类
{
public static synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public void hello() {
System.out.println("-----hello");
}
}
测试
public class Lock8Demo {
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
new Thread(() -> {
phone.sendEmail();
}, "a").start();
//暂停毫秒,保证a线程先启动
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone.hello();
}, "b").start();
}
}
结果
-----hello
-----sendEmail
10 有1个静态同步方法,有1个普通方法,有2部手机,请问先打印邮件还是hello
资源类
class Phone //资源类
{
public static synchronized void sendEmail() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----sendEmail");
}
public void hello() {
System.out.println("-----hello");
}
}
测试
public class Lock8Demo {
public static void main(String[] args)//一切程序的入口
{
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(() -> {
phone.sendEmail();
}, "a").start();
//暂停毫秒,保证a线程先启动
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
phone2.hello();
}, "b").start();
}
}
结果
-----hello
-----sendEmail
注意
阿里巴巴开发手册提到
原理
第一题和第二题
因为使用的是同一个对象锁 ,只要一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了, 其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一的一个线程去访问这些synchronized方法
锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法
第三题
一个对象 加个普通方法后发现和同步锁无关 所以先普通方法先执行
第四题
有2个对象,所以有2个不同的对象锁,情况会改变
第五题 和第六条
一个对象 或2个对象,有1个或2个不同的对象锁,但是 2个同步方法均都是 static 修饰的 所以这2个静态同步方法是属于 Class 的方法 , 对于静态同步方法,锁的是当前类的为为一个模板Class对象,如Phone.class唯一的一个模板。所以会按照 谁先调用的静态同步方法谁就先执行。
第七题和第八题
一个对象 或2个对象,有1个或2个不同的对象锁 ,但是 有一个 静态同步方法 和一个普通同步方法 ,所以静态同步方法,锁的是当前类的为为一个模板Class对象,而普通同步方法是锁的是当前对象this 即对象锁,所以 这两把锁是两个不同的对象,所以静态同步方法与普通同步方法之间是不会有竞态条件的 但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁。
至于第九题和第十题
一个对象 或2个对象,有1个或2个不同的对象锁,但是 有一个 静态同步方法 和一个普通方法,
而普通方法与同步锁无关,所以普通先执行
总结
同一对象:
同一对象访问不同的同步锁,是按照顺序执行
同一对象访问同步锁与普通方法,是执行普通方法
同一对象访问不同静态同步锁,按照谁先调用谁先执行
同一对象访问一个静态同步锁,一个同步锁,先执行同步锁
多个对象
多个对象访问不同同步锁,按照顺序执行
不同对象访问不同静态同步锁,按照谁先调用谁先执行
不同对象访问一个静态同步锁,一个同步锁,先执行同步锁即先出同步锁在出静态同步锁