标签: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