【多线程】多线程编程:线程同步
来源:互联网 发布:淘宝会查物流重量吗 编辑:程序博客网 时间:2024/05/19 00:51
线程同步:
为什么需要同步?
- 线程同步是为了防止多个线程访问一个数据对象时,对数据造成破坏。
- 线程的同步是保证多线程安全访问竞争资源的一种手段
同步和锁:
- Java中每个对象都有一个内置锁
- 获得一个对象的锁也称为:获取锁;锁定对象;在对象上锁定;在对象上同步
- 一个对象只有一个锁,所以如果一个线程获得该锁,该对象上的其他线程就没有可以获得的锁,直到第一个线程释放锁。也意味着任何其他线程都不能进入synchronized方法或代码块。
- 当程序运行到synchronized同步方法或代码块时,该对象锁才起作用
- 当线程运行到非静态的synchronied同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁,当线程运行到synchronized同步代码块时,自动获得锁定对象的锁。
如何理解:
很多人(线程)都想进入一个房间(对象),但是这个房间(对象)只有一把钥匙(锁),一次只能进一个人(线程)。要想进入房间,每次只能有一个人(线程)拿着钥匙(锁)进入房间(进入synchronized)。下一个人(线程)要等待上一个人(线程)走出房间(退出synchronized),把锁(钥匙)给自己,才能访问这个房间(对象)
对于同步,一般而言Java代码中需要完成两个操作:
- 把竞争访问的资源标识为private私有
- 同步哪些需要访问资源的代码,使用synchronized关键字来修饰方法或代码块,当synchronized方法执行完或发生异常时,会自动释放锁。
Code Demo:
模拟银行账户取款的资源竞争:一个银行账户支持在柜台和ATM机上取款,但是这两种取款方式不能同时进行。可以把这两种取款方式看做两个线程,他们竞争访问的资源就是银行账户中的存款。
public class BankDemo { public static void main(String[] args) { BankAccount bankAccount=new BankAccount(); BankThread counter=new BankThread(bankAccount); counter.start(); BankThread ATM=new BankThread(bankAccount); ATM.start(); }}class BankThread extends Thread{ private BankAccount bankAccount=null; public BankThread(BankAccount bankAccount){ this.bankAccount=bankAccount; } @Override public void run() { //从银行账户上取走400块 int money=bankAccount.takeMoney(400); System.out.println("Take Money from your account:"+money); }}class BankAccount{ private long deposit=5000; //当一个线程调用同步方法时,这个线程就获取了当前对象的锁 //其他线程再调用时,只能等待。 public synchronized long takeMoney(long number){ if(number<0){ return -1; }else if(deposit<0){ return -2; }else if(number-deposit>0){ return -3; }else{ try { //模拟取钱时的等待时间 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } deposit-=number; System.out.println("Deposit: "+deposit); } return deposit; }}
同步产生死锁的原因:
- 当一个线程已经获取对象1的锁,同时又想获取对象2的锁,而此时另一个线程当前已经持有的对象2的锁,而又想获取对象1的锁。这种互相等待对方释放锁的过程会导致死锁
- 尽量避免嵌套同步块
public class DeadLockDemo { public static void main(String[] args) { Example example=new Example(); DeadThread1 thread1=new DeadThread1(example); thread1.start(); DeadThread2 thread2=new DeadThread2(example); thread2.start(); }}class DeadThread1 extends Thread{ private Example example=null; public DeadThread1(Example example){ super(); this.example=example; } @Override public void run() { example.method1(); }}class DeadThread2 extends Thread{ private Example example=null; public DeadThread2(Example example){ super(); this.example=example; } @Override public void run() { example.method2(); }}class Example{ private Object obj1=new Object(); private Object obj2=new Object(); public void method1(){ synchronized (obj1){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj2){ System.out.println("method1"); } } } public void method2(){ synchronized (obj2){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj1){ System.out.println("method2"); } } }
0 0
- 【多线程】多线程编程:线程同步
- 多线程编程:线程同步
- 多线程编程与线程同步
- 多线程编程5 线程同步
- 多线程编程 线程互斥 线程同步
- .NET多线程编程(3):线程同步
- .NET多线程编程(3):线程同步
- .NET多线程编程(3):线程同步
- .NET多线程编程(3):线程同步
- c#多线程编程教学:线程同步
- .NET多线程编程(3):线程同步
- .NET多线程编程(3):线程同步
- .net多线程编程(3):线程同步
- .NET多线程编程(3):线程同步
- c#多线程编程教学:线程同步
- .NET多线程编程(3):线程同步
- 多线程编程实例----线程同步之事件
- 多线程编程实例----线程同步之互斥量
- java Method invoke 参数问题
- 最小生成树——Prim算法
- 质数筛选法
- Mysql 常用 SQL 语句集锦
- Multiple Contexts have a path of "/xxxx"问题解决思路
- 【多线程】多线程编程:线程同步
- ROS机器人Diego 1#制作(十四)机械臂的控制---arduino驱动
- 弹出广告真恶心
- hashmap
- http的get和post发送方法
- android--jni
- 状态
- android 语音聊天播放动画的问题
- 创建一个小球,3秒后变成两个,再过3秒变成4个,再过3秒变成8个,只可以写一个脚本,该怎么编写?