多线程 - 线程同步
线程同步
线程同步机制
点击链接跳转大佬网址
同步方法及同步块
同步方法
//模拟买票
public class TestDemo03 {public static void main(String[] args) {catHoust catHoust = new catHoust();Thread t1 = new Thread(catHoust,"A");Thread t2 = new Thread(catHoust,"B");Thread t3 = new Thread(catHoust,"C");t1.start();t2.start();t3.start();}
}class catHoust implements Runnable{//车票private int tickNumber = 10;@Overridepublic void run() {buyTick();}public synchronized void buyTick(){while (true){if (this.tickNumber <= 0){break;}System.out.println(Thread.currentThread().getName()+"买到了第"+tickNumber+"张票。");this.tickNumber --;}}
}
同步块
//大概这样 需要一个锁 ,这个锁是要操作标量的所属对象
synchronized (this){this.tickNumber --;
}
CopyOnWriteArrayList 一个线程安全的类
线程安全的集合类
//测试juc 安全类型包的集合
public class TestDemo04 {public static void main(String[] args) throws InterruptedException {//线程安全的集合类CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();for (int i = 0; i < 1000; i++) {new Thread(()->{list.add(Thread.currentThread().getName());}).start();}Thread.sleep(3000);System.out.println(list.size());}
}
死锁
多个线程互相抱着对方所需要的资源,然后形成死锁。
//死锁的测试
public class TestDemo05 {public static void main(String[] args) {Makeup g1 = new Makeup(0,"A");Makeup g2 = new Makeup(1,"B");g1.start();g2.start();}
}//口红
class Lipstick{}//镜子
class Mirror{}class Makeup extends Thread{//需要的资源 只有一份,用static 来保证只有一份static Lipstick lipstick = new Lipstick();static Mirror mirror = new Mirror();int choice;//选择String girname;//使用者姓名public Makeup( int choice,String girname){this.choice = choice;this.girname = girname;}@Overridepublic void run() {//化妆try {makeup();} catch (InterruptedException e) {e.printStackTrace();}}//化妆,互相持有对方的锁,就是需要对方的资源private void makeup() throws InterruptedException {if (choice == 0 ){synchronized (lipstick){//获取口红的锁System.out.println(this.girname + "获取口红的锁");//一秒后要镜子的锁Thread.sleep(1000);synchronized (mirror){//获取镜子的锁 System.out.println(this.girname + "获取镜子的锁");}}}else{synchronized (mirror){//获取镜子的锁System.out.println(this.girname + "获取镜子的锁");//一秒后要口红的锁Thread.sleep(1000);synchronized (lipstick){//获取口红的锁System.out.println(this.girname + "获取口红的锁");}}}}
}
执行结果为
A获取口红的锁
B获取镜子的锁
看上面的结果就可以看出少了两句结果,就是因为持有了对方的锁就导致了死锁。可以把持有对方资源的方法提到外面
//死锁的测试
public class TestDemo05 {public static void main(String[] args) {Makeup g1 = new Makeup(0,"A");Makeup g2 = new Makeup(1,"B");g1.start();g2.start();}
}//口红
class Lipstick{}//镜子
class Mirror{}class Makeup extends Thread{//需要的资源 只有一份,用static 来保证只有一份static Lipstick lipstick = new Lipstick();static Mirror mirror = new Mirror();int choice;//选择String girname;//使用者姓名public Makeup( int choice,String girname){this.choice = choice;this.girname = girname;}@Overridepublic void run() {//化妆try {makeup();} catch (InterruptedException e) {e.printStackTrace();}}//化妆,互相持有对方的锁,就是需要对方的资源private void makeup() throws InterruptedException {if (choice == 0 ){synchronized (lipstick){//获取口红的锁System.out.println(this.girname + "获取口红的锁");//一秒后要镜子的锁Thread.sleep(1000);}synchronized (mirror){//获取镜子的锁System.out.println(this.girname + "获取镜子的锁");}}else{synchronized (mirror){//获取镜子的锁System.out.println(this.girname + "获取镜子的锁");//一秒后要口红的锁Thread.sleep(1000);}synchronized (lipstick){//获取口红的锁System.out.println(this.girname + "获取口红的锁");}}}
}
再次执行结果为
A获取口红的锁
B获取镜子的锁
B获取口红的锁
A获取镜子的锁
这就是死锁的原因和解决方法了。
死锁避免方法
- 产生死锁的四个必要条件
- 互斥条件:一个资源每次只能被一一个进程使用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待条件 :若干进程之间形成- -种头尾相接的循环等待资源关系。
Lock锁
可重入锁。
可显示加锁,解锁。
推荐室友 try/cath的方式来写这个Lock
package com.mayb.State;import java.util.concurrent.locks.ReentrantLock;//模拟买票
public class TestDemo03 {public static void main(String[] args) {catHoust catHoust = new catHoust();Thread t1 = new Thread(catHoust,"A");Thread t2 = new Thread(catHoust,"B");Thread t3 = new Thread(catHoust,"C");t1.start();t2.start();t3.start();}
}
class catHoust implements Runnable{//车票private int tickNumber = 10;//定义可重入锁private final ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {buyTick();}public void buyTick(){while (true){try {//枷锁lock.lock();if (this.tickNumber <= 0){break;}Thread.sleep(1000);System.out.println(Thread.currentThread().getName()+"买到了第"+tickNumber+"张票。");this.tickNumber --;} catch (InterruptedException e) {e.printStackTrace();} finally {//解锁lock.unlock();}}}
}
synchronized与Lock的对比
Lock是显式锁(手动开启和关闭锁,别忘记关闭锁) synchronized是隐式锁, 出了
作用域自动释放Lock只有代码块锁,synchronized有代码块锁和方法锁
使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展
性(提供更多的子类)
优先使用顺序:
- Lock >同步代码块(已经进入了方法体,分配了相应资源) >同步方法(在方
法体之外)
线程池
package com.mayb.State;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TestDemo06 {public static void main(String[] args) {//开启连接 Executors.newFixedThreadPool(10); 参数为可以放多少线程池ExecutorService service = Executors.newFixedThreadPool(10);service.execute(new MyThread());service.execute(new MyThread());service.execute(new MyThread());//关闭连接service.shutdown();}
}class MyThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}
生产消费者问题 , 管程法,信号灯法
多线程 - 线程同步相关推荐
- java同步与死锁_Java多线程 - 线程同步与死锁
一.线程同步 1)模拟多个用户同时从银行账户里面取钱 ● Account 类:银行账户类,里面有一些账户的基本信息,以及操作账户信息的方法 //模拟银行账户 classAccount {private ...
- 第18章 多线程----线程同步
Java提供了线程同步的机制来防止资源访问的冲突. 1.线程安全 实际开发中,使用多线程程序的情况很多,如银行排号系统.火车站售票系统等.这种多线程的程序通常会发生问题. 以火车站售票系统为例,在代码 ...
- C#中的多线程-线程同步基础 (控制线程数量)
同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具: 简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程完成 锁系统 构成 目的 跨进程? 速度 loc ...
- 9 C++ Boost 多线程,线程同步
线程的创建 boost_thread,boost_system 多线程的创建 线程的参数传递 线程的创建方式 线程的join 加入join,回收线程线程中断 线程中断2, 线程组 boost 线程的死 ...
- Python多线程——线程同步
创建多线程 继承Thread类创建派生类,并重写__init__和run方法,实现自定义线程对象类: import threading import timeclass myThread(thread ...
- Java 多线程 线程同步
线程同步 1.发生在多个线程操作同一个资源 2.并发:同一个对象被多个线程同时操作 3.于是,就需要线程同步.线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等 ...
- 13-多线程01 实现多线程 线程同步 生产者消费者
1.实现多线程 1.1简单了解多线程[理解] 是指从软件或者硬件上实现多个线程并发执行的技术. 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能. 1.2并发和并行[理解] 并 ...
- java例程练习(多线程[线程同步问题])
//线程同步问题 public class TestThread implements Runnable{Timer timer = new Timer();public static void ma ...
- Linux多线程 | 线程同步
文章目录 前言 主要介绍四种常用的线程同步方式以及相关的函数接口. 一.线程同步 二.同步方法 1.互斥锁 2.信号量 3.条件变量 4.读写锁 总结 前言 主要介绍四种常用的线程同步方式以及相关的函 ...
最新文章
- Linux实战案例(5)关闭Centos的防火墙
- VS2005调试ASP.NET出现未能开始侦听端口解决办法
- 系统服务管理与控制程序(Init System/初始化系统)-- Systemd 的 Unit 配置文件详解
- DBeaver连接达梦|虚谷|人大金仓等国产数据库
- 织梦后台如何生成站点地图sitemap.xml
- java mysql查询语句_Mysql查询语句执行过程
- DateUtils封装
- 雷凌3070无线网卡linux驱动,3070无线网卡驱动,小编教你ralink3070无线网卡驱动
- 测试员一份工作坚持多久跳槽,才能完美提升薪资?
- 最新勒索软件WannaCrypt病毒感染前后应对措施
- android 大文件查找,大文件查找软件(WizTree)
- vlookup匹配的文字显示0_Excel | VLOOKUP函数使用详解
- .net EF 事务TransactionScope和BeginTransaction的用法
- 程序员的希波克拉底誓言
- VLAN通过多个交换机传输,实现同VLAN互通,不同VLAN不通
- 应用计算机解数学模型之我见,初中数学建模教学之我见
- 爬取京东商城中的书籍信息
- 【考研政治】徐涛马克思主义基本原理串讲 笔记(更新中)
- react-native APP图标和名字的配置
- Matlab 非线性回归