7
回答
java 多线程问题
【腾讯云】学生服务器套餐10元/月 >>>   
import org.junit.Test;

public class TestTry {

	class Ticket implements Runnable {
		private int count = 10;

		public void run() {
			while (true) {
				if (count > 0) {
					System.out.println(Thread.currentThread().getName()
							+ "...sale: " + count--);
					System.out.flush();
				}
			}
		}
	}

	@Test
	public void test() {
		Ticket t = new Ticket();

		new Thread(t).start();
		new Thread(t).start();
	}
}

上述代码中运行若干次,大多数都是正确结果,即只卖出1~10号票。但是有时候运行结果会出现相同票号,如下面所示:

Thread-1...sale: 10
Thread-2...sale: 10
Thread-2...sale: 8
Thread-2...sale: 7
Thread-2...sale: 6
Thread-2...sale: 5
Thread-2...sale: 4
Thread-2...sale: 3
Thread-2...sale: 2
Thread-2...sale: 1
Thread-1...sale: 9
不知为什么会出现这种问题,麻烦各位指点一下,谢谢。

举报
Triangle23
发帖于5年前 7回/311阅
共有7个答案 最后回答: 5年前
package com.duapp.itfanr;
public class Test {
		public static void main(String args[]){
		Ticket t = new Ticket();
		new Thread(t).start();
		new Thread(t).start();
	}
}

class Ticket implements Runnable {
	private int count = 10;
//	Object object = new Object();

	public void run() {
		while (true) {
			synchronized (this) {
				if (count > 0) {
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
					}
					System.out.println(Thread.currentThread().getName()
							+ "...sale: " + count--);
				}
			}
		}
	}
}
--- 共有 2 条评论 ---
itfanr回复 @Triangle23 : 成功了啊 5年前 回复
Triangle23你这个成功了吗?为什么我运行你的这段代码还是会中途停止? 5年前 回复

因为你两个线程共享的一个变量,

其实count--包括三个步骤,读取,修改,写入

中间线程切换时就会出现这种问题

解决方法就是在count--上加同步块


--- 共有 1 条评论 ---
Triangle23恩,是这样的,谢谢。 还想问一下如果在 System.out.println(Thread.currentThread().getName()+ "...sale: " + count--);之前加上 try { Thread.sleep(10); } catch (InterruptedException e) { } 会不会造成死锁啊 5年前 回复
我写的代码,不要用synchronized了,过时了,学习下Lock吧,更面向对象
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class AtomDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		ThreadDemo5 td = new ThreadDemo5();
		for (int i = 1; i <= 5; i++) {
			new Thread(td).start();
		}
	}
}

class ThreadDemo5 implements Runnable {

	private int count = 50;
	private Lock lock = new ReentrantLock();

	public void run() {

		while (true) {

			lock.lock();
			try {
				if (count == 0) {
					return;
				}
				System.out.println(Thread.currentThread().getName() + " "
						+ count--);
			} finally {
				lock.unlock();
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}
}

--- 共有 1 条评论 ---
Triangle23好的,我学习一下,谢谢你 5年前 回复

引用来自“itfanr”的答案

我今天看了一天 线程 代码块同步和函数同步 不会死锁的

那为什么程序会运行不下去呢?代码如下:

import org.junit.Test;

public class TestTry {

	class Ticket implements Runnable {
		private int count = 10;

		// public void run() {
		// while (true) {
		// if (count > 0) {
		// try {
		// Thread.sleep(1);
		// } catch (InterruptedException e) {
		// }
		// System.out.println(Thread.currentThread().getName()
		// + "...sale: " + count--);
		// }
		// }
		// }

		Object object = new Object();

		public void run() {
			while (true) {
				synchronized (object) {
					if (count > 0) {
						try {
							Thread.sleep(1);
						} catch (InterruptedException e) {
						}
						System.out.println(Thread.currentThread().getName()
								+ "...sale: " + count--);
					}
				}
			}
		}
	}

	@Test
	public void test() {
		Ticket t = new Ticket();

		new Thread(t).start();
		new Thread(t).start();
	}
}
运行结果如下:

Thread-1...sale: 10
Thread-1...sale: 9
Thread-1...sale: 8
运行到这里就不运行了

--- 共有 2 条评论 ---
Triangle23好的,没问题 5年前 回复
itfanr我手机上网不方便 两个小时后我给你答案 一起探讨 5年前 回复

引用来自“itfanr”的答案

package com.duapp.itfanr;
public class Test {
		public static void main(String args[]){
		Ticket t = new Ticket();
		new Thread(t).start();
		new Thread(t).start();
	}
}

class Ticket implements Runnable {
	private int count = 10;
//	Object object = new Object();

	public void run() {
		while (true) {
			synchronized (this) {
				if (count > 0) {
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
					}
					System.out.println(Thread.currentThread().getName()
							+ "...sale: " + count--);
				}
			}
		}
	}
}

你的代码可以, 用Object当锁也可以,可是用JUnit写再运行就不行了。代码如下:

package com.triangle23.test;

import org.junit.Test;

class Ticket implements Runnable {
	private int count = 10;

	// Object object = new Object();

	public void run() {
		while (true) {
			synchronized (this) {
				if (count > 0) {
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
					}
					System.out.println(Thread.currentThread().getName()
							+ "...sale: " + count--);
				}
			}
		}
	}
}

public class TestSecond {

	@Test
	public void test() {
		Ticket t = new Ticket();
		new Thread(t).start();
		new Thread(t).start();
	}

}

--- 共有 2 条评论 ---
Triangle23回复 @itfanr : 程序应该没有问题了,可能就是JUnit执行的问题,它没有人为设定的主函数,这个问题我再研究研究。谢谢你所有的回答,:) 5年前 回复
itfanrJUnit我没用过 不懂测试 5年前 回复
public class Test{
	
	public static void main(String[] args){
		Ticket t = new Ticket();
		Thread t1 =new Thread(t);
		Thread t2 =new Thread(t);
		//Thread t3 =new Thread(t);
		t1.start();
		t2.start();
		//t3.start();
	}
}

class Ticket implements Runnable{
		private int count=50;
		private Object lock = new Object();
	
		public void run(){
			while(true){
				synchronized(lock){
					if(count>0){
						try{
							System.out.println(Thread.currentThread().getName()+ "...sale: " + count--);
							lock.notifyAll();
							lock.wait();
						}catch(Exception e){
						}
					}else{
						lock.notifyAll();
						return;
					}
				}
			}
		}
	}
顶部