kos*_*osa 6 java multithreading
我有一个实现runnable的线程类和一个int计数器作为实例变量.两个同步方法添加和子.当我以某种方式运行我的测试类时,它会在几次打印错误的结果.据我所知,当一个方法同步时,整个对象将被锁定以供其他线程访问,每当我们得到相同的结果时,这个逻辑是什么?有些情况并非如此.我错过了什么吗?
我的机器是Windows 7,64位.
public class ThreadClass implements Runnable {
int counter = 0;
@Override
public void run() {
add();
sub();
}
public synchronized void add() {
System.out.println("ADD counter" + (counter = counter + 1));
}
public synchronized void sub() {
System.out.println("SUB counter" + (counter = counter - 1));
}
}
Run Code Online (Sandbox Code Playgroud)
识别TestClass
public class ThreadTest {
public static void main(String args[]) {
ThreadClass tc = new ThreadClass();
Thread tc0 = new Thread(tc);
tc0.start();
tc0.setPriority(Thread.MAX_PRIORITY);
Thread tc1 = new Thread(tc);
tc1.start();
tc1.setPriority(Thread.NORM_PRIORITY);
Thread tc2 = new Thread(tc);
tc2.start();
tc2.setPriority(Thread.MIN_PRIORITY);
}
}
Run Code Online (Sandbox Code Playgroud)
结果
ADD counter1
ADD counter2
SUB counter1
SUB counter0
ADD counter1
SUB counter0
Run Code Online (Sandbox Code Playgroud)
注意:您可能需要执行几次运行才能产生这种不一致.
您的结果看起来正确.
在执行方法期间,获得对象的排他锁,但是在add()和sub()调用之间,线程可以自由交错.
如果0在所有线程都运行之后总共得到了总数,那么它们都没有覆盖eathother并且访问counter被同步.
如果你希望counter只是顺序而不是命中,那么执行以下操作(只要不涉及其他类,这将使方法级同步0变为冗余):12
@Override
public void run() {
synchronize(this) {
add();
sub();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这使得线程的重点无用,因为您可以在单线程循环中执行此操作.
同步确实意味着所有线程在进入同步块之前都会阻塞等待获取锁。只有一个线程可以拥有该对象的锁,因此只有一个线程可以使用add()或sub()方法。
但是,这并不意味着有关线程顺序的任何其他内容。您正在启动三个线程 - 唯一的保证是它们不会通过同时运行add或方法而相互干扰。sub线程 1 可以调用add(),然后线程 3 可以调用add(),然后线程 2 可以调用add(),然后它们都可以调用sub()。或者他们也可以先打电话add(),然后sub()再打电话。或任何混合 - 唯一的要求是每个线程add()在调用之前调用sub(),并且不会有两个线程调用add()或sub()当另一个线程处于该方法中时。
旁白:在某些情况下,在 上同步可能是不好的形式this,因为它是公共的 - 通常首选使用内部私有Object来锁定,这样其他调用者就无法获取您的锁并违反您设计的任何锁定策略。
| 归档时间: |
|
| 查看次数: |
1725 次 |
| 最近记录: |