在java中一个类中可以有多个静态锁吗

yebdmbv4  于 2021-09-13  发布在  Java
关注(0)|答案(3)|浏览(486)

我有多个方法,我希望有静态锁,这样没有两个对象可以访问一个方法,但同时不同的方法不会被这些对象锁定,并且可以独立运行。

class A {
    private static final A lock1 = new A();
    private static final B lock2 = new B();

    public void method1() {
        synchronized (lock1) {
            // do something
        }
    }

    public void method2() {
        synchronized (lock2) {
            // do something
        }
    }
}

现在我希望这两个方法在被锁定时彼此独立,但同时我希望同一类的多个示例在单个方法中被锁定。
如何做到这一点?通过使用不同的类?这样做能做到这一点吗?

wbgh16ku

wbgh16ku1#

首先,这就足够了:

private static final A lock1 = new Object();
private static final B lock2 = new Object();

然后,随着你的实施,, method1method2 相互独立,但只有一个示例 method1method2 可以在的所有示例中运行 A . 如果希望允许的不同并发示例 A 以便 method1method2 多个不同的示例可以并发运行,只需声明锁而不需要 static .
换句话说:如果 a1a2 都是 A :
具有 static 锁,如果 a1.method1 正在运行, a2.method1 无法由其他线程运行
没有静电, a1.method1 只能由一个线程运行。 a1.method1a2.method1 可以同时运行。

eqoofvh9

eqoofvh92#

静电锁
如果锁定的对象位于静态字段中,则该特定类的所有示例都将共享该锁定。这意味着如果从该类创建的一个对象正在访问该类 static lock,则从该类创建的另一个对象无法访问该锁。
非静态锁
如果类有一个非静态锁,那么每个示例都有自己的锁,因此只有对同一对象的方法调用才会相互锁定。
例如,使用静态锁定对象时:
线程1调用 obj01.doSomething() 线程2调用 obj01.doSomething() ,将必须等待线程1完成
线程3调用 obj02.doSomething() ,还必须等待线程1(可能还有线程2)完成。
使用非静态锁定对象时:
线程1调用 obj01.doSomething() 线程2调用 obj01.doSomething() ,将必须等待线程1完成
线程3调用 obj02.doSomething() ,它可以继续,而不考虑线程1和线程2,因为这是一个新对象,它不依赖于类。
非静态锁基本上是对象级锁。静态锁是类级锁
对象级锁
java中的每个对象都有一个唯一的锁。如果线程想要在给定对象上执行同步方法,首先它必须获得该对象的锁。一旦线程获得了锁,就可以在该对象上执行任何同步方法。一旦方法执行完成,线程就会自动释放锁。

public class Example implements Runnable {

    @Override
    public void run() {
        objectLock();
    }
    public void objectLock() {
        System.out.println(Thread.currentThread().getName());
        synchronized(this) {
            System.out.println("Synchronized block " + Thread.currentThread().getName());
            System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
        }
    }
    public static void main(String[] args) {
        Example test1 = new Example();
        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test1);
        Example test2 = new Example();
        Thread t3 = new Thread(test2);
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
}

输出将是,,

t1
t3
Synchronized block t1
t2
Synchronized block t1 end
Synchronized block t3
Synchronized block t2
Synchronized block t3 end
Synchronized block t2 end

类级锁
java中的每个类都有一个唯一的锁,它只是一个类级锁。如果线程想要执行静态同步方法,那么该线程需要类级锁。一旦线程获得了类级锁,就可以执行该类的任何静态同步方法。一旦方法执行完成,线程就会自动释放锁。

public class Example implements Runnable {

    @Override
    public void run() {
        classLock();
    }
    public static void classLock() {
        System.out.println(Thread.currentThread().getName());
        synchronized(Example.class) {
            System.out.println("Synchronized block " + Thread.currentThread().getName());
            System.out.println("Synchronized block " + Thread.currentThread().getName() + " end");
        }
    }
    public static void main(String[] args) {
        Example test1 = new Example();
        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test1);
        Example test2 = new Example();
        Thread t3 = new Thread(test2);
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
}

输出如下所示,

t1
t3
t2
Synchronized block t1
Synchronized block t1 end
Synchronized block t2
Synchronized block t2 end
Synchronized block t3
Synchronized block t3 end

当前情景
在这里,您有两个方法,如果一个方法使用一个锁访问,另一个使用另一个锁,那么在您的实现中,您可以有两个对象使用彼此的方法,但不能使用相同的方法。

obj01.method01();
obj02.method02();

这是可能的,但不是这个

obj01.method01();
obj02.method01();

obj02 必须等到 obj01 完成这个方法。

vof42yt1

vof42yt13#

锁不是用于方法的。锁用于数据。使用互斥锁的全部目的是确保不同的线程总能看到一些共享数据的一致视图。
您的代码示例显示了两个锁,但没有显示锁应该保护的数据。这样更好:

class Example {
    // R-State variables
    private final Object lockR = new Object();
    private A a = ...;
    private B b = ...;
    private C c = ...;

    // G-State variables
    private final Object lockG = new Object();
    private Alpha alpha = ...;
    private Beta beta = ...;
    private Gamma gamma = ...;

    public void methodR() {
        synchronized (lockR) {
            // do something with a, b, and c.
        }
    }

    public void methodG() {
        synchronized (lockG) {
            // do something with alpha, beta, and gamma.
        }
    }
}

我的 Example 类有两个独立的变量组; a , b ,及 c ,及 alpha , beta ,及 gamma . 每个独立组都有自己的独立锁。任何访问“r-state”变量的方法都应该是 synchronized (lockR)... ,同样适用于“g状态”变量和 lockG .
如果一个方法需要同时访问两个组,那么它必须锁定这两个锁。但是请注意!这可能表明这两个群体并不是真正独立的。如果它们之间存在任何依赖关系,那么实际上应该只有一个锁。
还请注意,我删除了 static 从这个例子。那纯粹是无缘无故的改变。我憎恶 static . 你也应该厌恶它,但这是另一个与锁定无关的主题。

相关问题