JAVA学习——多线程同步
来源:互联网 发布:网络型数据采集机 编辑:程序博客网 时间:2024/05/18 01:33
上一篇对多线程的基本用法进行了简单的小结,这一篇着重说一下多线程同步问题
使用多线程,由于多线程并发执行的特点,所以大大的提高了程序的运行效率,但是,当多个线程去访问同一个资源时,也会出现一些安全问题
就拿我们之前所说过的售票案例。
/** * 模拟窗口售票 * * @author Shawn·Zhang */public class Example01 {public static void main(String[] args) {TicketWindow tw = new TicketWindow();new Thread(tw, "售票口一").start();new Thread(tw, "售票口二").start();new Thread(tw, "售票口三").start();new Thread(tw, "售票口四").start();}}class TicketWindow implements Runnable {private int tickets = 10;public void run() {while (tickets > 0) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "正在发售第"+ tickets-- + "张票");}}}
测试结果:
在售票程序while循环中添加了sleep()方法,,这样也就是模拟了售票过程中,线程的延迟。
由于有延迟,当票号减为1时,假设线程1此时出售1号票,对票号进行判断之后,进入while循环,在售票之前通过sleep()方法让线程休眠,这时线程二会进行售票,由于此时此时票号仍为1,因此线程2也会进入循环,同理,四个线程都会进入循环,休眠结束后,四个线程都会卖票,这样就相当于将票号减了四次,结果中也就出现了0、-1、-2这样的现象
所以为了线程的安全问题,我们引入同步代码块以及同步方法
同步代码块
synchronized(lock){
操作共享资源代码块
}
利用java的同步机制,可以保证在多个线程使用同一个资源时,用于处理共享资源的代码任何时候都只有一个线程进行访问
优化后的代码:
/** * 模拟窗口售票 * @author Shawn·Zhang */public class Example01 {public static void main(String[] args) {TicketWindow tw = new TicketWindow();new Thread(tw,"售票口一").start();new Thread(tw,"售票口二").start();new Thread(tw,"售票口三").start();new Thread(tw,"售票口四").start();}}class TicketWindow implements Runnable {private int tickets = 10;Object lock = new Object();@Overridepublic void run() {while (true) {synchronized (lock) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}if(tickets>0){System.out.println(Thread.currentThread().getName() + "正在发售第"+ tickets-- + "张票");}else{break;}}}}}测试结果:
从测试结果可以看出,没有出现不正确的票。这是因为售票的代码实现了同步,之前出现的线程安全问题得以解决。
同步方法
与同步代码块同理,作用相同,只是书写格式有区别,在这里也写出来,以供学习
synchronized 返回值类型 方法名(){}
以售票案例为例,将上述的代码修改后,如下:
/** * 模拟窗口售票 * @author Shawn·Zhang */public class Example01 {public static void main(String[] args) {TicketWindow tw = new TicketWindow();new Thread(tw,"售票口一").start();new Thread(tw,"售票口二").start();new Thread(tw,"售票口三").start();new Thread(tw,"售票口四").start();}}class TicketWindow implements Runnable {private int tickets = 10;@Overridepublic void run() {while (true) {saleTickets();//调用售票方法if(tickets<=0){break;}}}private synchronized void saleTickets(){if(tickets>0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "正在发售第"+ tickets-- + "张票");}}}
结果可以参考同步代码块的测试结果。
死锁
在同步问题上,需要注意死锁问题,就是两个线程在运行的过程中,都在等待对方的锁,这样就会使得程序停滞
在开发中,要避免死锁的情况
public class Example06 {public static void main(String[] args) {Thread t1 = new Thread(new DeadLock(true));Thread t2 = new Thread(new DeadLock(false));t1.start();t2.start();}}class DeadLock implements Runnable{private boolean flag;//定义boolean类型的变量flagstatic Object locka = new Object();//定义锁对象lockastatic Object lockb = new Object();//定义锁对象lockbpublic DeadLock(boolean flag) {//有参构造方法this.flag = flag;}@Overridepublic void run() {if(flag){while(true){synchronized(locka){//锁对象上的同步代码块System.out.println("if locka");synchronized (lockb) {//锁对象上的同步代码块System.out.println("if lockb");}}}}else{while(true){synchronized(lockb){//锁对象上的同步代码块System.out.println("else lockb");synchronized (locka) {//锁对象上的同步代码块System.out.println("else locka");}}}}}}测试结果会出现死锁现象
0 0
- JAVA学习——多线程同步
- java多线程学习——同步
- JAVA学习——java多线程的同步和异步
- Java 学习————多线程同步
- Java多线程学习笔记——从Java JVM对多线程数据同步的一些理解
- java多线程学习2-同步
- java多线程学习笔记(三) ——多线程实例火车票问题+同步synchronized初接触
- 【java多线程学习】多线程的同步
- java多线程—Java 多线程同步的五种方法
- JAVA多线程同步——学无止境
- Java多线程——同步(一)
- Java多线程——同步(二)
- Java多线程——高级同步机制
- java多线程——同步的前提
- java多线程——线程同步问题
- java多线程——同步与锁
- Java多线程——线程同步
- Java多线程——线程同步(2)
- Struts2配置
- Ubuntu14.04下安装scrapy
- 去除字符串中的重复字符
- operator new在C++中的各种写法
- win10 internal power error
- JAVA学习——多线程同步
- C++模板学习之单链表的实现
- CRF分词的纯Java实现
- flash乱码解决方案
- c++primer之顺序容器(添加元素)
- leetcode 275: H-Index II
- 有图有话 | 高效人士的一天,你能做到几条?
- SqlHelper类
- eclipse启动闪退总结