【我的Java笔记】多线程安全问题 & 同步机制
来源:互联网 发布:知乎的影响力 编辑:程序博客网 时间:2024/06/01 09:00
目前所学过安全的类:
(1)Vector (多用于合并流)
(2)StringBuffer
(3)Hashtable
(4)Collections类中的:public static <T> List<T> synchronizedList(List<T> list)返回指定列表支持的同步(线程安全的)列表
1.检验多线程是否安全的标准:
(1)当前是否为多线程环境
(2)多线程环境中是否有共享数据
(3)是否有多条语句对共享数据进行操作
2.解决多线程不安全的方法(同步代码块):
将多条语句对共享数据的操作进行更改:使用同步代码块将对共享数据操作的代码包起来
格式:
(1)在成员位置声明同步锁对象(任意对象都可以)
(2)Synchronized(同步锁对象){
// 对共享数据进行操作的多条语句
}
3.同步锁对象要求
(1)可以是任意类(Object类以及任意自定义对象)
(2)同步方法:将Synchronized关键字至于方法声明,变成同步方法
①非静态方法:可以将Synchronized关键字加入到方法声明上,变成同步方法(同步锁对象为:this)
②静态方法:若同步方法为静态方法,需通过反射获取锁对象(锁对象为:当前类名.class)
4.同步机制解决线程安全问题的弊端
(1)执行效率低(每一个线程抢到CPU的执行权时别的线程无法进入)
(2)容易出现死锁现象(两个或两个以上的线程出现互相等待的情况)
例:模拟电影院售票,一共有100张票,三个窗口同时开售
注:加入延迟操作和线程的随机性会导致线程的安全问题,出现一张票被卖多次和出现负票的情况
// 测试类public class SellTicketTest {public static void main(String[] args) {// 创建SellTicket对象SellTicket st = new SellTicket();// 创建线程Thread t1 = new Thread(st, "窗口1");Thread t2 = new Thread(st, "窗口2");Thread t3 = new Thread(st, "窗口3");// 启动线程t1.start();t2.start();t3.start();}}
// 自定义定义线程类public class SellTicket implements Runnable {// 定义共有数据100张票private static int tickets = 100;// 设置同步锁对象Object obj = new Object();@Overridepublic void run() {// 假设一直有票while(true) {// 同步代码块:设置锁对象,一条线程进来之后会“关门”,别的线程不会再进来synchronized (obj) {// 让线程睡眠0.1秒try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");}}}}}
非同步方法:
// 自定义定义线程类public class SellTicket implements Runnable {// 定义共有数据100张票private static int tickets = 100;// 定义一个变量private int i;@Overridepublic void run() {// 假设一直有票while (true) {if (i % 2 == 0) {// 非静态方法this代表锁对象synchronized (this) {// 让线程睡眠0.1秒try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");}}} else {sellTicket();}}}// 非静态同步方法private synchronized void sellTicket() {// 让线程睡眠0.1秒try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");}}}
静态同步方法:
// 自定义定义线程类public class SellTicket implements Runnable {// 定义共有数据100张票private static int tickets = 100;// 定义一个变量private int i;@Overridepublic void run() {// 假设一直有票while (true) {if (i % 2 == 0) {// 静态方法SellTicket.class代表锁对象synchronized (SellTicket.class) {// 让线程睡眠0.1秒try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");}}} else {sellTicket();}i++;}}// 静态同步方法private static synchronized void sellTicket() {// 让线程睡眠0.1秒try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");}}}
同步机制可能会出现的死锁现象:
// 测试类public class DieLockTest {public static void main(String[] args) {// 创建线程类对象DieLock dl1 = new DieLock(true);DieLock dl2 = new DieLock(false);// 启动线程dl1.start();dl2.start();}}// 自定义锁class MyLock {//创建两把锁对象public static final Object objA = new Object() ;public static final Object objB = new Object() ;}// 自定义线程类class DieLock extends Thread {//定义一个成员变量private boolean flag ;public DieLock(boolean flag){this.flag = flag ;}@Overridepublic void run() {//dl1,dl2线程if(flag){synchronized(MyLock.objA){System.out.println("if objA");synchronized (MyLock.objB) {System.out.println("if objB");}}//代码执行完毕,objA锁相当于才能被释放掉}else {//dl2synchronized (MyLock.objB) {System.out.println("else objB");synchronized(MyLock.objA){System.out.println("else objA");}}}}}
运行后会出现这样的情况:
由于两个线程之间出现了互相等待的情况,所以导致了死锁。
而正常情况是这样:
由于线程的运行具有随机性,所以多运行几次后也会出现理想的情况
阅读全文
0 0
- 【我的Java笔记】多线程安全问题 & 同步机制
- Java笔记 - 多线程的安全问题
- java笔记之java多线程的安全问题
- Java笔记3 多线程<1>线程概述、多线程的创建、多线程的安全问题、静态同步函数的锁、死锁
- Java多线程的同步机制
- Java多线程的同步机制
- java多线程的同步机制
- 【我的Java笔记】多线程_使用Lock锁对象解决线程安全问题
- Java 多线程的安全问题
- java多线程-多线程的安全问题-多线程同步代码块-锁Synchronized
- java多线程同步机制
- java多线程同步机制
- Java多线程同步机制
- Java多线程同步机制
- JAVA 多线程,同步机制
- java多线程同步机制
- Java 多线程同步机制
- java 多线程同步机制
- 远程连接MYSQL提示Host is not allowed to connect to this MySQL server
- 关于拷贝文件后的权限问题
- selenium的下载地址
- cocos creator 系统事件监听方法
- 头像上传代码
- 【我的Java笔记】多线程安全问题 & 同步机制
- HtmlAgilityPack官方文档(一)【Parser】
- 蓝桥杯-考察团组成
- postDelayed(Runnable runnable ,long delayMillis)只执行一次
- PHP把驼峰式命名方式转换成下划线分隔命名的字符串
- pycharm专业版激活
- 安装JDK与环境变量配置
- hi3516v300gpio驱动编译错误1
- 单链表选择排序