线程安全
2019-01-04 09:48:10来源:博客园 阅读 ()
1. 什么叫线程安全?
多线程对共享资源进行写的操作,受到其他线程的干扰,导致数据偶问题,这种现象叫做线程安全问题。
package com.cn.test.thread; public class TrainThread implements Runnable { /** * 两个线程进行售票100张 */ private int trainTicket = 100; @Override public void run() { while (trainTicket > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } // 进行售票 System.out.println(Thread.currentThread().getName() + "开始售票:" + (100 - trainTicket + 1) + "张"); trainTicket--; } } public static void main(String[] args) { TrainThread train = new TrainThread(); Thread t1 = new Thread(train,"窗口1"); Thread t2 = new Thread(train,"窗口2"); t1.start(); t2.start(); } }
运行结果:
窗口1开始售票:1张
窗口2开始售票:1张
窗口1开始售票:3张
窗口2开始售票:3张
窗口1开始售票:5张
窗口2开始售票:5张
窗口1开始售票:7张
窗口2开始售票:7张
窗口2开始售票:9张
窗口1开始售票:9张
窗口2开始售票:11张
窗口1开始售票:12张
窗口2开始售票:13张
窗口1开始售票:14张
窗口2开始售票:15张
窗口1开始售票:16张
窗口2开始售票:17张
窗口1开始售票:18张
窗口2开始售票:19张
窗口1开始售票:20张
窗口2开始售票:21张
窗口1开始售票:22张
窗口2开始售票:23张
窗口1开始售票:24张
窗口2开始售票:25张
窗口1开始售票:26张
窗口2开始售票:27张
窗口1开始售票:28张
窗口2开始售票:29张
窗口1开始售票:30张
窗口2开始售票:31张
窗口1开始售票:32张
窗口2开始售票:33张
窗口1开始售票:34张
窗口2开始售票:35张
窗口1开始售票:36张
窗口2开始售票:37张
窗口1开始售票:38张
窗口2开始售票:39张
窗口1开始售票:40张
窗口2开始售票:41张
窗口1开始售票:42张
窗口2开始售票:43张
窗口1开始售票:44张
窗口2开始售票:45张
窗口1开始售票:46张
窗口2开始售票:47张
窗口1开始售票:48张
窗口2开始售票:49张
窗口1开始售票:50张
窗口2开始售票:51张
窗口1开始售票:52张
窗口2开始售票:53张
窗口1开始售票:54张
窗口2开始售票:55张
窗口1开始售票:56张
窗口2开始售票:57张
窗口1开始售票:58张
窗口2开始售票:59张
窗口1开始售票:60张
窗口2开始售票:61张
窗口1开始售票:62张
窗口2开始售票:63张
窗口1开始售票:64张
窗口2开始售票:65张
窗口1开始售票:66张
窗口2开始售票:67张
窗口1开始售票:68张
窗口2开始售票:69张
窗口1开始售票:70张
窗口2开始售票:71张
窗口1开始售票:72张
窗口2开始售票:73张
窗口1开始售票:74张
窗口2开始售票:75张
窗口1开始售票:76张
窗口2开始售票:77张
窗口1开始售票:78张
窗口2开始售票:79张
窗口1开始售票:80张
窗口2开始售票:81张
窗口1开始售票:82张
窗口2开始售票:83张
窗口1开始售票:84张
窗口2开始售票:85张
窗口1开始售票:86张
窗口2开始售票:87张
窗口1开始售票:88张
窗口2开始售票:89张
窗口1开始售票:90张
窗口2开始售票:91张
窗口1开始售票:92张
窗口2开始售票:93张
窗口1开始售票:94张
窗口2开始售票:95张
窗口1开始售票:96张
窗口2开始售票:97张
窗口1开始售票:98张
窗口2开始售票:99张
窗口1开始售票:100张
窗口2开始售票:101张
线程安全解决的办法:
使用多线程之间同步synchronized或使用锁(lock)。
为什么使用线程同步或使用锁能解决线程安全问题呢?
将可能发生线程安全的代码,在同一时刻只有一个线程对此进行操作,代码执行完毕之后释放锁之后才让其他线程并发执行,这样就会解决线程安全的问题。
什么是线程同步?
多个线程共享同一个资源,不会受到其他线程的干扰。
解决办法1:
同步代码块。 将可能发生线程安全的代码用同步代码块包裹起来。
synchronized(同一个数据) {
可能会发生线程冲突问题
}
同步代码块需要传递的对象(锁对象):就是锁住这个对象,表示这个对象正在为我服务,其他人不能用(非synchronized代码块、方法除外)。
while (trainTicket > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj) { // 进行售票 if (trainTicket > 0) { System.out.println(Thread.currentThread().getName() + "开始售票:" + (100 - trainTicket + 1) + "张"); trainTicket--; } } }
解决办法2:
同步函数,在发生线程安全的函数中加入sychnorized关键字。
静态同步函数:
方法上加上static关键字,使用synchronized 关键字修饰 或者使用类.class文件。静态的同步函数使用的锁是 该函数所属字节码文件对象可以用 getClass方法获取,也可以用当前 类名.class 表示。
死锁:
同步中嵌套同步,导致锁无法释放
package com.cn.test.thread; public class TestDeadThread implements Runnable { private boolean flag = true; private static int trainCount = 100; private Object mutex = new Object(); @Override public void run() { if (flag) { while(true) { synchronized (mutex) { sale(); } } } else { while (true) { sale(); } } } private synchronized void sale() { synchronized (mutex) { if (trainCount > 0) { try { Thread.sleep(40); } catch (Exception e) { } System.out.println(Thread.currentThread().getName() + ",出售 第" + (100 - trainCount + 1) + "张票."); trainCount--; } } } public static void main(String[] args) throws InterruptedException { TestDeadThread test1 = new TestDeadThread(); Thread t1 = new Thread(test1,"thread-1"); Thread t2 = new Thread(test1,"thread-2"); t1.start(); Thread.sleep(40); test1.flag = false; t2.start(); } }
运行结果:
thread-1,出售 第1张票. thread-1,出售 第2张票. thread-1,出售 第3张票. thread-1,出售 第4张票. thread-1,出售 第5张票. thread-1,出售 第6张票. thread-1,出售 第7张票. thread-1,出售 第8张票. thread-1,出售 第9张票. thread-1,出售 第10张票. thread-1,出售 第11张票. thread-1,出售 第12张票. thread-1,出售 第13张票. thread-1,出售 第14张票. thread-1,出售 第15张票. thread-1,出售 第16张票. thread-1,出售 第17张票. thread-1,出售 第18张票. thread-1,出售 第19张票. thread-1,出售 第20张票. thread-1,出售 第21张票. thread-1,出售 第22张票. thread-1,出售 第23张票. thread-1,出售 第24张票. thread-1,出售 第25张票.
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:Java时间和时间戳的相互转换
下一篇:Java实现简单的DoS攻击
- 5月到6月程序员到底经历了和什么,工资狂跌***元,你是否也 2020-06-10
- 为什么阿里巴巴Java开发手册中不允许魔法值出现在代码中? 2020-06-09
- 计算机基础到底是哪些基础?为什么很重要! 2020-06-08
- 最详细的java多线程教程来了 2020-06-08
- 系统化学习多线程(一) 2020-06-08
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash