标签:dsa class ring san not sys jdk1.5 tar dex
1.多线程重复出现某结果 如下:已经卖完了和仓库已经满了会出现多次
public class ProductAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Product product = new Product(clerk); Consumer consumer = new Consumer(clerk); new Thread(product).start(); new Thread(consumer).start(); } } class Clerk { private int goodsNumber = 0; public synchronized void get() { if(goodsNumber<=10){ System.out.println("商品A库存数量为:"+ ++goodsNumber); }else{ System.out.println("仓库已经满了"); } } public synchronized void sale(){ if(goodsNumber>0){ System.out.println("商品A库存数量为:"+ --goodsNumber); }else{ System.out.println("已经卖完了"); } } } class Product implements Runnable{ private Clerk clerk; public Product(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.get(); } } } class Consumer implements Runnable{ private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.sale(); } } }
2. 多线程同步锁造成死锁,如下:商人找买家先要钱,买家找商人先要货造成死锁,原因在于:一个不释放锁,另一个得不到锁
public class GoodsAndMoney { public static void main(String[] args) { Trader trader = new Trader(buyer.money); buyer buyer = new buyer(Trader.goods); new Thread(trader).start(); new Thread(buyer).start(); } } class Trader implements Runnable { public static String goods = "goods"; public static String money; public Trader(String money) { Trader.money = money; } @Override public void run() { while (true) { synchronized (goods) { synchronized (money) { } } System.out.println("先交钱~后交货~"); } } } class buyer implements Runnable { public static String money = "money"; public static String goods; public buyer(String goods) { buyer.goods = goods; } @Override public void run() { while (true) { synchronized (money) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (goods) { } } System.out.println("先交货~后交钱~"); } } }
3.虚假唤醒,如下:当最后一次出现卖完了的时候,出售线程处于wait状态,所以线程不会结束
public class ProductAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Product product = new Product(clerk); Consumer consumer = new Consumer(clerk); new Thread(product).start(); new Thread(consumer).start(); } } class Clerk { private int goodsNumber = 0; public synchronized void get() { if(goodsNumber<1){ System.out.println("商品A库存数量为:"+ ++goodsNumber); this.notifyAll(); }else{ System.out.println("仓库已经满了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void sale(){ if(goodsNumber>0){ System.out.println("商品A库存数量为:"+ --goodsNumber); this.notifyAll(); }else{ System.out.println("已经卖完了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Product implements Runnable{ private Clerk clerk; public Product(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.get(); } } } class Consumer implements Runnable{ private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.sale(); } } }
4.虚假唤醒,线程进入wait后会释放线程的锁,后面的线程有可能到wait位置,被唤醒后,两个线程运行后导致结果超出范围
package volatile1; public class ProductAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Product product = new Product(clerk); Consumer consumer = new Consumer(clerk); new Thread(product).start(); new Thread(consumer).start(); new Thread(product).start(); new Thread(consumer).start(); } } class Clerk { private int goodsNumber = 0; public synchronized void get() { if (goodsNumber >= 5) { System.out.println("仓库已经满了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("商品A库存数量为:" + ++goodsNumber); this.notifyAll(); } public synchronized void sale() { if (goodsNumber <= 0) { System.out.println("已经卖完了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("商品A库存数量为:" + --goodsNumber); this.notifyAll(); } } class Product implements Runnable { private Clerk clerk; public Product(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.get(); } } } class Consumer implements Runnable { private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.sale(); } } }
5.在4的代码上加上循环可以解决虚假唤醒,因为被唤醒后会经过while需要满足条件才能跳出,而且第一次到while里时值会变化,所以不会连着出现已经满了
package volatile1; public class ProductAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Product product = new Product(clerk); Consumer consumer = new Consumer(clerk); new Thread(product).start(); new Thread(consumer).start(); new Thread(product).start(); new Thread(consumer).start(); } } class Clerk { private int goodsNumber = 0; public synchronized void get() { while (goodsNumber >= 5) { System.out.println("仓库已经满了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("商品A库存数量为:" + ++goodsNumber); this.notifyAll(); } public synchronized void sale() { while (goodsNumber <= 0) { System.out.println("已经卖完了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("商品A库存数量为:" + --goodsNumber); this.notifyAll(); } } class Product implements Runnable { private Clerk clerk; public Product(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.get(); } } } class Consumer implements Runnable { private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.sale(); } } }
5.jdk1.5以后的lock方法解决以上问题
package volatile1; public class ProductAndConsumer2 { public static void main(String[] args) { Clerk clerk = new Clerk(); Product product = new Product(clerk); Consumer consumer = new Consumer(clerk); new Thread(product).start(); new Thread(consumer).start(); new Thread(product).start(); new Thread(consumer).start(); } } class Clerk { private int goodsNumber = 0; public synchronized void get() { while (goodsNumber >= 5) { System.out.println("仓库已经满了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("商品A库存数量为:" + ++goodsNumber); this.notifyAll(); } public synchronized void sale() { while (goodsNumber <= 0) { System.out.println("已经卖完了"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("商品A库存数量为:" + --goodsNumber); this.notifyAll(); } } class Product implements Runnable { private Clerk clerk; public Product(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.get(); } } } class Consumer implements Runnable { private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { clerk.sale(); } } }
标签:dsa class ring san not sys jdk1.5 tar dex
原文地址:http://www.cnblogs.com/gg128/p/7617771.html