关于Java多线程---------(3,同步与死锁)
来源:互联网 发布:怎么弄个java服务器 编辑:程序博客网 时间:2024/06/05 10:08
1,线程同步的作用
2,同步代码块以及同步方法的作用
3,死锁的产生
在多线程的开发中,同步与死锁是非常重要的,那么问题来了,对于这两个东西,需要思考几个问题。
1,代码的什么地方需要同步;2,如何实现同步;3,实现同步之后有哪些副作用。
1,问题的出现,为什么要有同步?(什么是同步,为什么要有同步)
举个例子来说,卖火车票,售卖火车票会有多个售票站点,一趟火车的座位数是固定的,把各个售票点就可以理解为各个线程,也就是说,所有的线程共同拥有同一份的票源,同时不能一个席位卖两张票出去。
class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ if(ticket>0){ // 还有票 System.out.println("卖票:ticket = " + ticket-- ); } } }};public class SyncDemo01{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定义线程对象 Thread t1 = new Thread(mt) ; // 定义Thread对象 Thread t2 = new Thread(mt) ; // 定义Thread对象 Thread t3 = new Thread(mt) ; // 定义Thread对象 t1.start() ; t2.start() ; t3.start() ; }};
在实际情况中,票务信息是存储在数据库中的,从数据库中读取信息,通过网络显示在售票设备上,这个过程中,肯定是存在时间延迟的,
class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ if(ticket>0){ // 还有票 try{ Thread.sleep(300) ; // 加入延迟 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println("卖票:ticket = " + ticket-- ); } } }};public class SyncDemo01{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定义线程对象 Thread t1 = new Thread(mt) ; // 定义Thread对象 Thread t2 = new Thread(mt) ; // 定义Thread对象 Thread t3 = new Thread(mt) ; // 定义Thread对象 t1.start() ; t2.start() ; t3.start() ; }};
发现,坏了,卖出的票数有负数了,代码出问题了呀。。。。这个情况他到底是怎么回事呢?为什么加入延迟就出现这个问题了呢?
分析一下这个问题:
好气哦~~~写出来代码是为了解决实际问题,不是过家家闹着玩的,实际情况中,就是会有各种复杂的情况,就会出现网络不畅通的情况,总不能不让延迟出现呀。。。。
那么这个在有延迟的情形下,如何完美的解决这个买票问题呢?
2,同步解决问题:(同步的作用)
解决资源共享的同步操作问题,可以使用同步代码块以及同步方法两种方式进行完成。
代码块分为4种:
普通代码块:是直接定义在方法之中的;
构造快:是直接定义的类中对的;(优先于构造方法执行,会重复调用)
静态块:是使用static关键字声明的,(优先于构造快执行,只执行一次)
同步代码块:是使用synchronized关键字声明的代码块,称为同步代码块;
同步代码块解决问题
同步的时候,必须指明同步的对象,一般情况下,会将当前对象作为同步的对象,使用this表示。
class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ synchronized(this){ // 要对当前对象进行同步 if(ticket>0){ // 还有票 try{ Thread.sleep(300) ; // 加入延迟 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println("卖票:ticket = " + ticket-- ); } } } }};public class SyncDemo02{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定义线程对象 Thread t1 = new Thread(mt) ; // 定义Thread对象 Thread t2 = new Thread(mt) ; // 定义Thread对象 Thread t3 = new Thread(mt) ; // 定义Thread对象 t1.start() ; t2.start() ; t3.start() ; }};
从运行结果可以发现,成功加入了同步操作,所以不会产生负数的情况,但是程序执行的效率明显降低很多,没有加上同步操作的时候,是异步执行的,异步执行明显速度更快。
同步方法解决问题
class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ this.sale() ; // 调用同步方法 } } public synchronized void sale(){ // 声明同步方法 if(ticket>0){ // 还有票 try{ Thread.sleep(300) ; // 加入延迟 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println("卖票:ticket = " + ticket-- ); } }};public class SyncDemo03{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定义线程对象 Thread t1 = new Thread(mt) ; // 定义Thread对象 Thread t2 = new Thread(mt) ; // 定义Thread对象 Thread t3 = new Thread(mt) ; // 定义Thread对象 t1.start() ; t2.start() ; t3.start() ; }};
3,同步的副作用—-死锁
1,资源共享时,需要进行同步操作(解决延时导致的问题);
2,如果同步过度,会产生死锁的现象;
死锁一般情况下就是表示表示互相等待,是在程序运行时出现的一种问题。
举个例子,将上面张三李四的例子实现代码:
class Zhangsan{ // 定义张三类 public void say(){ System.out.println("张三对李四说:“你给我画,我就把书给你。”") ; } public void get(){ System.out.println("张三得到画了。") ; }};class Lisi{ // 定义李四类 public void say(){ System.out.println("李四对张三说:“你给我书,我就把画给你”") ; } public void get(){ System.out.println("李四得到书了。") ; }};public class ThreadDeadLock implements Runnable{ private static Zhangsan zs = new Zhangsan() ; // 实例化static型对象 private static Lisi ls = new Lisi() ; // 实例化static型对象 private boolean flag = false ; // 声明标志位,判断那个先说话 public void run(){ // 覆写run()方法 if(flag){ synchronized(zs){ // 同步张三 zs.say() ; try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(ls){ zs.get() ; } } }else{ synchronized(ls){ ls.say() ; try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(zs){ ls.get() ; } } } } public static void main(String args[]){ ThreadDeadLock t1 = new ThreadDeadLock() ; // 控制张三 ThreadDeadLock t2 = new ThreadDeadLock() ; // 控制李四 t1.flag = true ; t2.flag = false ; Thread thA = new Thread(t1) ; Thread thB = new Thread(t2) ; thA.start() ; thB.start() ; }};
以上就是死锁的操作状态,都是在相互等待着地方的回答。
总结:
1,多个线程在访问同一资源的时候,需要进行同步操作;
2,同步使用synchronized关键字完成;
3,同步分为,同步代码块和同步方法;
4,过多的同步有可能造成死锁,死锁是程序在运行时的一种表现状态;
①同步的原因是为了解决延迟可能导致的访问同一资源导致的问题;②过多的同步同样导致了死锁的问题,这个死锁的问题,同样是因为延迟导致的———所以,从根本上来说,如果是网络服务,提高网速是根本的解决办法,人类也是一直致力于4g,5g,8g,的研究呀,如果是本地服务来说,提高硬件执行效率,提高并发效率是关键——-双核CPU,四核CPU,i3,i7,i9系列的CPU,厉害了呀,,,,,人类的智慧简直是无穷的呀。。。。。。
- 关于Java多线程---------(3,同步与死锁)
- Java 多线程同步与死锁
- JAVA - 多线程 - 同步与死锁
- Java多线程之同步与死锁
- Java多线程之同步与死锁
- Java多线程的同步与死锁
- Java多线程 线程同步与死锁
- 多线程 同步与死锁
- java多线程同步死锁
- 多线程之同步与死锁
- java 同步与死锁
- Java多线程同步死锁例程
- Java 多线程同步、死锁问题
- java多线程-同步和死锁
- 黑马程序员-JAVA基础-多线程的安全、同步与死锁
- java多线程(同步与死锁问题,生产者与消费者问题)
- JAVA提高篇(34)-- Java多线程的同步与死锁
- 9. 多线程 Part 3 同步与死锁 --- 学习笔记
- CodeForces
- 先验,后验和似然
- Springmvc @ResponseBody与@RequestBody忽略空值字段
- 宝塔 Linux/Windows 面板
- 为什么淹死的都是会水的?
- 关于Java多线程---------(3,同步与死锁)
- Machine Learning Course 1 and 2
- 软件架构理论体系v4.0的畅想
- 后台服务的系统错误和逻辑错误不同
- 电力拖动自动控制系统(一)直流调速系统篇--不可逆系统(1)
- jq写点击那个那个显示其他隐藏用到toggleClass
- svn: E000013: Commit failed (details follow)
- JAVA的数据在内存中的表现形式
- Java finalize方法使用