java多线程 信号量(Semaphore),死锁
2016-10-26 19:17
387 查看
信号量可以用来限制访问公共资源。在访问公共资源之前,线程必须从信号量获取许可。在访问资源之后,这个线程必须将许可返回给信号量,
为了创建信号量,必须使用可选的公平策略来确定许可的数量。任务通过调用信号量acquire() 方法来获得许可,可通过调用信号量的release()方法来释放许可。一旦获得许可,信号量中可用许可的数量减一。一旦许可呗释放掉,信号量的可用许可的总数加1。
使用只有一个许可的信号量可以模拟一个相互排斥的锁。
避免死锁
有时两个或者多个线程需要在一个共享对象上获取锁,这可能导致死锁(Deadlock),也就是说,每个线程已经锁定一个对象,而且正在等待另一个对象。下面是一个很可能造成死锁的例子
但是使用资源排序技术就可以轻易的避免死锁的发生。原理就是为每一个需要锁的对象排序,确保每个线程都按照这个顺序来获取锁。假设,按照locker1、locker2的顺序对连个对象排序。采用资源排序技术,线程2必须先获得locker1上的锁,然后才能获取lock2上面的锁。一旦线程1 获取的locker1上的锁,线程2必须等待locker1的锁。所以不会在发生死锁现象。
为了创建信号量,必须使用可选的公平策略来确定许可的数量。任务通过调用信号量acquire() 方法来获得许可,可通过调用信号量的release()方法来释放许可。一旦获得许可,信号量中可用许可的数量减一。一旦许可呗释放掉,信号量的可用许可的总数加1。
使用只有一个许可的信号量可以模拟一个相互排斥的锁。
import java.util.concurrent.*; public class SemaphoreTest { private static Account _account = new Account(); public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); for(int i=0; i<100;i++) { executor.execute(new depositTask()); } executor.shutdown(); while(!executor.isTerminated()) { } System.out.println("任务完成"); System.exit(0); } private static class depositTask implements Runnable { @Override public void run(){ _account.deposit(1); } } public static class Account { private static Semaphore _semaphore = new Semaphore(1,true); private int _menoeyy=0; private int GetMenoey(){ return _menoeyy; } private void deposit(int monery) { try { _semaphore.acquire(); _menoeyy+=monery; Thread.sleep(50); System.out.println(getAccountInfo()); } catch ( InterruptedException ex) { } finally { _semaphore.release(); } } public String getAccountInfo(){ return "当前账户与额为:¥"+_menoeyy; } } }
避免死锁
有时两个或者多个线程需要在一个共享对象上获取锁,这可能导致死锁(Deadlock),也就是说,每个线程已经锁定一个对象,而且正在等待另一个对象。下面是一个很可能造成死锁的例子
import java.util.concurrent.*; public class DeadlockTest { public static byte[] locker1 = new byte[0]; public static byte[] locker2 = new byte[0]; public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(100); for(int i =0 ;i <50;i++){ executor.execute(new DeadlockTask1()); executor.execute(new DeadlockTask2()); } executor.shutdown(); while(!executor.isTerminated()){ } System.exit(0); } private static class DeadlockTask1 implements Runnable { public void run() { <span style="color: rgb(204, 0, 0);">synchronized(locker1){</span> System.out.println(" DeadlockTask1 获得锁 locker1 没有死锁!"); <span style="color: rgb(204, 0, 0);">synchronized(locker2){</span> System.out.println(" DeadlockTask1 获得锁 locker2 没有死锁!"); } } } } private static class DeadlockTask2 implements Runnable { public void run() { <span style="color: rgb(153, 0, 0);">synchronized(locker2){</span> System.out.println(" DeadlockTask2 获得锁 locker2 没有死锁!"); <span style="color: rgb(153, 0, 0);">synchronized(locker1){</span> System.out.println(" DeadlockTask2 获得锁 locker1 没有死锁!"); } } } } }
但是使用资源排序技术就可以轻易的避免死锁的发生。原理就是为每一个需要锁的对象排序,确保每个线程都按照这个顺序来获取锁。假设,按照locker1、locker2的顺序对连个对象排序。采用资源排序技术,线程2必须先获得locker1上的锁,然后才能获取lock2上面的锁。一旦线程1 获取的locker1上的锁,线程2必须等待locker1的锁。所以不会在发生死锁现象。
import java.util.concurrent.*; public class DeadlockTest { public static byte[] locker1 = new byte[0]; public static byte[] locker2 = new byte[0]; public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(100); for(int i =0 ;i <50;i++){ executor.execute(new DeadlockTask1()); executor.execute(new DeadlockTask2()); } executor.shutdown(); while(!executor.isTerminated()){ } System.exit(0); } private static class DeadlockTask1 implements Runnable { public void run() { <span style="color: rgb(153, 0, 0);">synchronized(locker1){</span> System.out.println(" DeadlockTask1 获得锁 locker1 没有死锁!"); <span style="color: rgb(204, 0, 0);">synchronized(locker2){</span> System.out.println(" DeadlockTask1 获得锁 locker2 没有死锁!"); } } } } private static class DeadlockTask2 implements Runnable { public void run() { <span style="color: rgb(204, 0, 0);">synchronized(locker1){</span> System.out.println(" DeadlockTask2 获得锁 locker2 没有死锁!"); <span style="color: rgb(204, 0, 0);">synchronized(locker2){</span> System.out.println(" DeadlockTask2 获得锁 locker1 没有死锁!"); } } } } }
相关文章推荐
- Java多线程-新特征-信号量Semaphore
- Java多线程系列--【JUC锁11】- Semaphore信号量的原理和示例
- Java多线程-新特征-信号量Semaphore
- java多线程-Semaphore信号量使用
- JAVA多线程--信号量(Semaphore)
- JAVA多线程--信号量(Semaphore)
- Java多线程-新特征-信号量Semaphore
- JAVA多线程--信号量(Semaphore)
- 信号量(semaphore),互斥锁(mutex)解决哲学家死锁问题
- [No00003D]操作系统Operating Systems信号量的代码实现Coding Semaphore &死锁处理Deadlock
- 学习笔记 java多线程 信号量(Semaphore),死锁
- Java并发编程之Semaphore(信号量)
- 体验 Java 并发 api,用不同方式实现信号量锁(Semaphore)(6)
- java线程同步——信号量(Semaphore)
- C#多线程--信号量(Semaphore)
- GCD-信号量(dispatch_semaphore_t)
- Multi-Programming-17 Semaphore & CountDownLatch信号量和计数栓之间的关系
- c用信号量(Semaphore)实现消费者生产者同步
- 信号量同步 semaphore
- java多线程-concurrent-Semaphore信号量