JAVA——线程安全(synchronized)
来源:互联网 发布:数据清洗怎么做? 编辑:程序博客网 时间:2024/06/16 02:36
卖票的程序
我们在卖票的中间暂停一段时间。观察程序的运行结果。
class Ticket implements Runnable{ private int ticket = 20; public void run() { while(true) { if(ticket>0) { try { Thread.sleep(100); } catch(Exception e) { } System.out.println(Thread.currentThread().getName()+"---sale :"+ticket--); } } }}class TicketDemo1{ public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t);//创建了一个线程 Thread t2 = new Thread(t);//创建了一个线程 Thread t3 = new Thread(t);//创建了一个线程 Thread t4 = new Thread(t);//创建了一个线程 t1.start(); t2.start(); t3.start(); t4.start(); }}
通过分析,发现,打印出,0,-1.-2等错票。这是什么原因呢?有人说是博主故意加了sleep,其实吧,正常情况下,cpu要在多个线程之间进行来回切换的,不可以一直运行到底的,当卖票的时候cpu突然就切出去了。所以这里只是模仿了一下。
分析原因
当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分。还没有执行完,另一个线程就参与进来执行。导致共享数据的错误。解决办法
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。JAVA对于多线程的安全问题提供了专业的解决方法。就是同步代码块。synchronized(对象){ //需要被同步的代码}
对象如同锁。持有锁的线程可以在同步中进行。没有持有锁的线程即使获取了cpu的执行权,也进不去,因为没有获得锁。例子
高铁上的卫生间,一个人进去了,门外就显示红色灯表明已经有人了,等ok出来以后,灯又变绿了。
同步的前提
1、必须要有两个或者两个以上的线程。(多个人想去上厕所)
2、必须使多个线程使用同一个锁。(上的必须是同车厢的厕所)
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程都需要判断锁,较为消耗资源。
class Ticket implements Runnable{ private int ticket = 20; Object o = new Object(); public void run() { while(true) { synchronized(o) //线程运行到这里判断锁,就相当于一个标志位,获得锁以后就把标志位置位,其他线程进不来。当该线程执行完出去以后,会把标志位置回去。 { if(ticket>0) { try { Thread.sleep(100); } catch(Exception e) { } System.out.println(Thread.currentThread().getName()+"---sale :"+ticket--); } } } }}class TicketDemo1{ public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t);//创建了一个线程 Thread t2 = new Thread(t);//创建了一个线程 Thread t3 = new Thread(t);//创建了一个线程 Thread t4 = new Thread(t);//创建了一个线程 t1.start(); t2.start(); t3.start(); t4.start(); }}
例子:
银行有一个金库。
有两个储户分别存300元,每次存100,存3次;
class Bank{ Object obj = new Object(); private int sum; public void add(int n) { synchronized(obj) { sum = sum +n; try { Thread.sleep(10); } catch(Exception e){} System.out.println("sum = "+sum); } }}class Cus implements Runnable{ private Bank b = new Bank(); public void run() { for(int x= 0;x<3;x++) { b.add(100); } }}class BankDemo{ public static void main(String[] args) { Cus c = new Cus(); Thread t1 = new Thread(c); Thread t2 = new Thread(c); t1.start(); t2.start(); }}
普通代码块和同步代码块有什么区别呢?其实就是同步代码块有其特有的性质(加锁)。试想函数能否变为同步呢?答案是肯定的!
class Bank{ Object obj = new Object(); private int sum; public synchronized void add(int n) { sum = sum +n; try { Thread.sleep(10); } catch(Exception e){} System.out.println("sum = "+sum); }}class Cus implements Runnable{ private Bank b = new Bank(); public void run() { for(int x= 0;x<3;x++) { b.add(100); } }}class BankDemo{ public static void main(String[] args) { Cus c = new Cus(); Thread t1 = new Thread(c); Thread t2 = new Thread(c); t1.start(); t2.start(); }}
如何找问题?
1、明确哪些代码是多线程运行的代码
2、明确共享数据
3、明确多线程运行代码中哪些语句是操作共享数据的。
死锁
Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待那些根本不可能被释放的锁,从而导致所有的工作都无法完成。假设有两个线程,分别代表两个饥饿的人,他们必须共享刀叉并轮流吃饭。他们都需要获得两个锁:共享刀和共享叉的锁。
假如线程 “A”获得了刀,而线程“B”获得了叉。线程“A”就会进入阻塞状态来等待获得叉,而线程“B”则阻塞来等待“A”所拥有的刀。
class Test implements Runnable{ private boolean flag; Test(boolean flag) { this.flag = flag; } public void run() { if(flag) { synchronized(MyLock.locka) { System.out.println("if locka!"); synchronized(MyLock.lockb) { System.out.println("if lockb!"); } } } else { synchronized(MyLock.lockb) { System.out.println("if lockb!"); synchronized(MyLock.locka) { System.out.println("if locka!"); } } } }}class MyLock{ static Object locka = new Object(); static Object lockb = new Object();}class DeadLockTest{ public static void main(String[] args) { Thread t1 = new Thread(new Test(true)); Thread t2 = new Thread(new Test(false)); t1.start(); t2.start(); }}
0 0
- JAVA——线程安全(synchronized)
- 【Java】 线程安全 synchronized
- Java中线程安全(synchronized)
- Java synchronized的理解!(线程安全,线程同步)
- java线程安全之synchronized理解篇(一)
- java线程安全之synchronized代码块(六)
- java synchronized详解 线程安全与线程非安全
- 【Java多线程】synchronized与线程安全
- synchronized ReentrantLock 线程安全
- synchronized 线程同步安全
- Synchronized和线程安全
- JAVA线程同步——synchronized
- 【Java基础】线程笔记——synchronized
- java并发编程:线程安全-线程同步-synchronized和lock
- Java 线程安全问题—synchronized锁机制
- 线程安全,线程同步,synchronized
- 线程—synchronized、volatile
- 转—java 线程安全
- 关于别名(alias)的尴尬
- jquery.cookie.js 的配置
- Java的jdk配置
- unity 设计模式
- Python 字符串操作
- JAVA——线程安全(synchronized)
- SSO单点登录
- 关于文件读写
- 学生成绩管理系统(链表的实现)
- Jquery - ajax url路径问题
- HDU 1520Anniversary party 树形dp
- Python系列(一)转义字符
- 关于mysql锁表的几种形式
- 为MT7688 SPI添加N个SPI接口