1

并且请不要陷入认为您可以锁定 A 类的任意实例并且会以某种方式锁定 A 类的另一个实例的陷阱。这是一个经典的初学者错误。

在我理解它之前,我犯了几次错误。但是静态锁对象可以正常工作。

我的线程

package com.replanet;

public class MyThread extends Thread {

    private int x, y;
    private static Object lock3 = new Object();

    public MyThread(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public void run() {
        super.run();
        try {
            test_Method();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private void test_Method() throws InterruptedException {
        synchronized (lock3) {
            System.out.println("test_Method " + Thread.currentThread().getName());
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                if (i == Integer.MAX_VALUE / 2) {
                    Thread.sleep(2000);
                    System.out
                            .println("Leaving test_Method on " + Thread.currentThread().getName());
                    return;
                }
            }
        }
    }

}

用法

package com.replanet;

public class Main {

    public static void main(String[] args) {

        MyThread myThread1 = new MyThread(1, 2);
        MyThread myThread2 = new MyThread(1, 2);
        myThread1.start();
        myThread2.start();
    }
}

输出

test_Method Thread-0
Leaving test_Method on Thread-0
test_Method Thread-1
Leaving test_Method on Thread-1

带有非静态锁定对象的输出(不适合我)

test_Method Thread-0
test_Method Thread-1
Leaving test_Method on Thread-1
Leaving test_Method on Thread-0

static使用锁定对象是个好主意吗?

4

3 回答 3

3

您可以锁定Class自身 - 这更有意义且更易于阅读:

private void test_Method() throws InterruptedException {
        synchronized (MyThread.class) {
            System.out.println("test_Method " + Thread.currentThread().getName());
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                if (i == Integer.MAX_VALUE / 2) {
                    Thread.sleep(2000);
                    System.out
                            .println("Leaving test_Method in " + Thread.currentThread().getName());
                    return;
                }
            }
        }
    }

或者,如果您不需要将该方法作为实例方法:

private static synchronized void test_Method() throws InterruptedException {
            System.out.println("test_Method " + Thread.currentThread().getName());
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                if (i == Integer.MAX_VALUE / 2) {
                    Thread.sleep(2000);
                    System.out
                            .println("Leaving test_Method in " +  Thread.currentThread().getName());
                    return;
                }
            }
    }

您可能还想阅读 new(ish) Lock类。

于 2013-02-19T09:40:51.850 回答
1

静态相比,让 MyThread 共享一个锁对象会更好。更面向对象。

于 2013-02-19T09:40:13.590 回答
0

它是静态成员还是实例成员取决于您希望它拥有的范围,但绝对一个好的做法是拥有一个私有对象来锁定。这是锁定(显然是公共的)类对象的主要优势。

于 2013-02-19T09:45:05.827 回答