我只是编写了一些代码来测试多个线程如何同步,但我无法得到我预期的结果。代码可以启动3个线程,但只有一个线程来处理共享资源。我的代码出错了。< / p>
class ThreadDemo1{
public static void main (String[] args){
MultiThread tt = new MultiThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class MultiThread implements Runnable {
int tickets = 100;
Object _lock = new Object();
public void run () {
System.out.println(Thread.currentThread().getName());
synchronized(_lock) {
while (true) {
if (tickets>0) {
try {
Thread.sleep(10);
} catch (Exception e) {}
System.out.println(Thread.currentThread().getName() + " is selling "+tickets--);
}
}
}
}
}
答案 0 :(得分:2)
你在按住锁时正在睡觉。如果要这样做,没有理由多线程。
public void run () {
System.out.println(Thread.currentThread().getName());
while(tickets > 0) {
synchronized(_lock) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + tickets--);
}
}
try {
Thread.sleep(10);
} catch (Exception e) {
}
}
}
我猜测sleep
是您处理的占位符。如果可能的话,你应该在synchronized块中进行检查和减量,但是在它之外进行冗长的处理。
为了使锁和多线程能够对你做任何有用的事情,你必须确保你的synchronized
代码花费尽可能少的时间,因为那是只能由一个线程运行的代码一次。
在您的代码中,唯一没有效的单线程是您的第一个System.println
。
仅供参考,考虑到这一点,如果您的打印报表准确但可能无序,那么最好是:
public void run () {
System.out.println(Thread.currentThread().getName());
while(tickets > 0) {
int oldTickets = 0;
synchronized(_lock) {
if (tickets > 0) {
oldTickets = tickets--;
}
}
if(oldTickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + oldTickets);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}
答案 1 :(得分:0)
[1]首先,您发布的代码中存在一些不良做法/错误:
(1)锁定对象是单身的更好。您可以使用静态字段对象或类本身(因为内存中只有一个类)
Object _lock = new Object();
private static final Object _lock = new Object();
(2)将while(true) {...}
放出同步块。在您的代码中,如果第一个线程获得Lock,它将处理所有票证并且不会停止。
应该让每个线程尝试在循环的每次迭代中获得Lock。
(3)对于Thread.sleep(10)
,我猜你的意思是线程正在做一些繁重的工作。但是将这种代码置于同步块(或其他名称:关键区域)并不是一个好习惯。因为只有一个线程可以同时访问同步块。您的代码行为就像一个单线程程序,因为其他线程必须等到当前正在运行的线程完成其工作。
请参阅下面的代码:
public class ThreadDemo1 {
public static void main(String[] args) {
MultiThread tt = new MultiThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
public class MultiThread implements Runnable {
private static int tickets = 100;
private static final Object _lock = new Object();
public void run() {
System.out.println(Thread.currentThread().getName());
while (tickets > 0) {
try {
synchronized (_lock) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + tickets--);
}
}
Thread.sleep(10);
} catch (Exception e) {
}
}
}
}
[2]其次,如果您只想在挑选票证时同步线程。尝试使用Atomic*
类而不是synchronized块,它是No-lock并且会为您带来更好的性能。例如:
import java.util.concurrent.atomic.AtomicInteger;
public class MultiThreadAtomic implements Runnable {
private static AtomicInteger tickets = new AtomicInteger(100);
public void run() {
System.out.println(Thread.currentThread().getName());
int ticketsRemaining = 0;
while ((ticketsRemaining = tickets.getAndDecrement()) > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + ticketsRemaining);
try {
Thread.sleep(10);
}
catch(InterruptedException ie) {}
}
}
}