这是我为研究线程而创建的测试代码。它由分配给同一个Runnable的两个线程组成。他们要扣除5成int,并停止如果int是不够大,扣除5事情是,线程1“阿尔法”不断循环,直到它半路内环路,在这种情况下是5,那么线程2“ beta“开始。这是我无法理解的一种特殊行为。我错过了什么?
public class synconizedThread implements Runnable {
int balance = 100;
public void run() {
checkAmmount();
}
public void checkAmmount() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ "checks balance: " + balance);
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
withDrawAmmount();
}
}
}
public void withDrawAmmount() {
if (balance <= 0) {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Balance is " + balance + " not enough");
}
else {
balance = balance - 5;
System.out.println(Thread.currentThread().getName()
+ "Whitdraws, balance left: " + balance);
}
}
public static void main(String[] args) {
Runnable myJob = new synconizedThread();
Thread alpha = new Thread(myJob);
alpha.setName("alpha");
Thread beta = new Thread(myJob);
beta.setName("beta");
alpha.start();
beta.start();
}
}
答案 0 :(得分:3)
您正在同步整个循环,因此第一个线程进入循环,然后在循环完成之前不会放弃CPU。
相反,您可能希望同步循环的每次迭代,这样线程就有机会交替。
您还要将呼叫同步到sleep(),这可能不是您想要做的事情。您可能希望将其移出同步之外。
public void checkAmmount() {
for (int i = 0; i < 10; i++) {
synchronized (this) {
System.out.println(Thread.currentThread().getName()
+ "checks balance: " + balance);
withDrawAmmount();
}
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
答案 1 :(得分:3)
我看到两个问题:
synchronized
块内。所以无论谁得到那个锁都会先执行循环。将synchronized
放在循环中。然后一个线程将在迭代结束时释放锁,并在下一个开始时再次竞争它,并且您将具有并发性。例如,制作withDrawAmount()
方法synchronized
。 (如果这样做,请确保将println
的线程ID移至withDrawAmount()
内。)Thread.sleep()
不释放锁定,因此不能解决循环问题在synchronized
内的问题。你可能应该完全接受每个Thread.sleep()
呼叫,因为它们只会减慢速度。与以往一样,您应该尽量保持关键部分 - synchronized
内的部分 - 尽可能小,以获得最大的并发性。同步withDrawAmount()
应该没问题,特别是一旦你摆脱了sleep()
次呼叫。如果您想获得一些乐趣并尝试查看是否可以获得更大的吞吐量,请查看java.util.conccurent.atomic.AtomicInteger
答案 2 :(得分:1)
你的第一个线程进入同步块,循环10次迭代并在每次迭代时撤回5,然后离开同步块。
因此,当完成10次迭代(并且余额为50)时,它将停止运行,离开同步块,允许第二个线程运行并执行其10次迭代。
答案 3 :(得分:1)
它是synchronized
关键字。你可以在整个for循环中使用它,所以无论谁先到达它都可以运行整个for循环。
当线程A使用它时,线程B无法访问该变量 - 它被A锁定。
如果你想同时扣除两者,你应该在for循环中移动synchronized
。
答案 4 :(得分:0)
据我了解你的问题,你的问题是线程alpha已经在他的循环中途,直到线程beta开始。 synchronized关键字阻止所有其他线程访问同步对象。您可以将synchronized关键字放在循环中,以便每个线程进入,然后每次都离开监视器
另外,默认情况下,线程不一定得到相等的cpu时间。因此,线程alpha会在您调用start()方法后立即开始工作,并且已经过了一半,直到线程&#34; beta&#34;甚至是由主线程
启动