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



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

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
}
}
}

现在,当它被锁定时,我希望这两个方法彼此独立,但同时我希望同一类的多个实例被锁定在一个方法中。

如何做到这一点?通过使用不同的类?这样做能做到吗?

首先,这就足够了:

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

然后,在您的实现中,method1method2彼此独立,但在A的所有实例中只能运行method1method2的一个实例。如果您想允许A的不同并发实例,以便不同实例的method1method2可以并发运行,只需声明没有static的锁即可。

换句话说:如果a1a2A的实例:

  • 使用static锁,如果a1.method1正在运行,则其他线程无法运行a2.method1
  • 在没有静态的情况下,a1.method1只能由一个线程运行。CCD_ 17和CCD_

锁不适用于方法。锁用于数据。使用互斥锁的全部目的是确保不同的线程总是能看到一些共享数据的一致视图。

您的代码示例显示了两个锁,但没有显示锁应该保护的数据。这更好:

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类有两组独立的变量;abc,以及alphabetagamma。每个独立组都有自己的独立锁。任何访问";R状态";变量应该是synchronized (lockR)...;G-State";变量和CCD_ 27。

如果一个方法需要同时访问两个组,那么它必须锁定两个锁。但是注意!可能是这两个群体并非真正独立的迹象。如果它们之间有任何依赖关系,那么实际上应该只有一个锁。


另外请注意,我从示例中删除了static。那纯粹是一个无偿的改变。我讨厌static。你也应该对此深恶痛绝,但这是一个与锁定无关的不同主题。

静态锁
如果锁定的对象位于静态字段中,则该特定的所有实例都将共享该锁。这意味着,如果从该类创建的一个对象正在访问static锁,则从该类中创建的另一个对象无法访问该锁。

非静态锁
如果类有一个非静态锁,那么每个实例都将有自己的锁,因此只有对同一对象的方法调用才会相互锁定。

例如,当您使用静态锁对象时:

  • 线程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();

CCD_ 37必须等到CCD_ 38完成该方法。

相关内容

最新更新