1.2 多个线程多个锁
来源:互联网 发布:网络玄幻小说典藏版 编辑:程序博客网 时间:2024/06/03 20:16
概述
多个线程中,如果每个线程操作的对象是不同的,那么就会为每个线程产生一把锁,这个时候,在不同的线程中,锁是不起作用的。
代码
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类)
- 1.2 多个线程多个锁
- 线程-多个线程多个锁
- 多个线程多个锁
- 并发编程(2)-多个线程多个锁
- lua 多个线程
- 多个线程调用同一个线程函数
- 线程传入多个参数
- Mysql kill多个线程
- 多个并行线程运算
- 用一个线程模拟多个线程,减少线程数量~
- 用一个线程模拟多个线程,减少线程数量~
- 多线程系列(二)---多个线程多个锁
- java线程安全篇之synchronized 多个线程多个锁(二)
- 线程2:线程通信事件机制(单线程、两个线程、多个线程通信)
- 在一个线程中产生多个线程
- 多个线程调用同一个线程函数的方法
- 多个线程是否可以共用一个线程函数
- java线程——多个线程之间切换执行
- 191.m1-Fragment页面优化,继承BaseFragment
- 回环变位(2017校招一模-----循环单词)
- 135. Candy
- Android StudioDebug调试详细大全
- 50多条实用mysql数据库优化建议
- 1.2 多个线程多个锁
- 377. Combination Sum IV | Leetcode Dynamic Programming
- leetcode 44. Wildcard Matching
- 限时独占2个月:曝OPPO R11前期独家使用骁龙660
- 输入输出流 (文件读写)
- leetcode-java.T013_RomarToInteger 罗马数字转成整数数字
- SUDT 3926 bLue的二叉树 [KMP or hash]【思维】
- 简单的在线留言系统
- leetcode-java.T012_IntegerToRoman 数字转罗马数字