1.2 多个线程多个锁 蔚落 2022-06-14 00:09 116阅读 0赞 ### 概述 ### 多个线程中,如果每个线程操作的对象是不同的,那么就会为每个线程产生一把锁,这个时候,在不同的线程中,锁是不起作用的。 ### 代码 ### MultiThread.java public class MultiThread { private int num = 0; public synchronized void printNum(String tag) throws InterruptedException { if (tag.equals("a")) { num = 100; System.out.println("tag a, set num over!"); Thread.sleep(1000); } else { num = 200; System.out.println("tag b, set num over!"); } System.out.println("tag " + tag + ", num = " + num); } public static void main(String[] args) { MultiThread m1 = new MultiThread(); MultiThread m2 = new MultiThread(); Thread t1 = new Thread(() -> { try{ m1.printNum("a"); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread t2 = new Thread(() -> { try{ m2.printNum("b"); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start(); t2.start(); } } 说明:定义了一个printNum方法,并给这个方法加了锁,这个方法内部是一个简单的if else判断而已,很简单。底下的main方法中,创建了两个MultiThread对象,分别为m1和m2,接下来又创建l了两个线程,分别是t1和t2,这两个线程的实现方式是直接使用匿名类创建对象的方式,可以直接使用接口,这里又使用了lamda表达式,所以看起来比较简略,实际上是创建的Runnable接口的对象,其中括号中的内容是覆写run方法的内容,可以看到两个不同的线程分别调用了不同对象的printNum方法,那么结果会是怎样的呢? > tag a, set num over! > tag b, set num over! > tag b, num = 200 > tag a, num = 100 结果和我们预想的不对吗?当然不对,预想的应该是 > tag a, set num over! > tag a, num = 100 > tag b, set num over! > tag b, num = 200 这样才对,因为我们加了synchronized 关键字啊。 原因是这样的,因为我们这两个线程分别调用的是两个对象的printNum方法,虽然进行了加锁,但是他们并不是一个对象,也就是说,这个同步锁是加在对象上的,并没有加在类级别上,不同的对象调用这个方法,同步锁是没有用的。 那么如何让对象方法加锁执行呢,也就是让同步锁起作用呢,那就需要使用static关键字,代码修改为: private static int num = 0; public static synchronized void printNum(String tag) throws InterruptedException { if (tag.equals("a")) { num = 100; System.out.println("tag a, set num over!"); Thread.sleep(1000); } else { num = 200; System.out.println("tag b, set num over!"); } System.out.println("tag " + tag + ", num = " + num); } 这样子再次执行查看效果: > tag a, set num over! > tag a, num = 100 > tag b, set num over! > tag b, num = 200 结果就和我们预期的一样了,那么为什么加上static之后就可以了呢,因为我们加了static关键字之后,这个方法就变成了类方法,也就是说,这个方法是和类相关的,和某个对象是无关的了,所以就可以达到加锁的效果了。所以我们查看结果,就是a先执行,然后b才执行。 ### 总结: ### synchronized取得的锁都是对象锁,而不是把一段代码当做锁,所以示例代码中那个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),两个对象,线程获取的就是两个不同的锁,他们互不影响。 有一种情况则是相同的锁,即在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)
还没有评论,来说两句吧...