锁的几个易错点

2021-02-02  本文已影响0人  小船儿爱学习

1、禁止使用高层并发对象的内置锁

实现java.util.concurrent.locks包中的Lock或Condition接口的类,被认为是高层并发对象。使用这些对象的内置锁是有问题的。使用Lock对象的内置锁的代码很可能与使用Lock接口的代码交互,这样可能会被误认为它们使用同一个锁来保护数据,而实际上使用了两个不同的锁,这样使用将无法保护数据。

\\ 错误示例(ReentrantLock)
private final Lock lock = new ReentrantLock();

public void doSomething() {
      synchronized(lock) {
          // do something
      }
}

上述错误示例中,doSomething()方法中,基于ReentrantLock的内置锁实现同步而不是基于被ReentrantLock封装的可重入的互斥锁实现同步。

\\ 正确示例(lock()、unlock())
private final Lock lock = ReentrantLock();

public void doSomething() {
      lock.lock();
      try {
          // do something
      } finally {
          lock.unlock();
      }
}

2、不可以用实例锁来同步静态数据

\\ 示例
public class CountBoxes implements Runnable {
    private static volatile int counter;

    private final Object lock = new Object();

    @Override
    public void run() {
        synchronized (lock) {
            counter++;
        }
    }

    public static void main(String[] args) {
        for (int i = 0; 1 < 2; i++) {
            new Thread(new CountBoxes()).start();
        }
    }
}

3、禁止基于getClass()返回的类对象进行同步

基于Object.getClass()方法的返回值同步可能会导致不符合预期的行为。当类实现继承时,子类只能基于子类进行锁定。子类与基类的Class对象是完全不同的。
当声明一个类的方法为同步方法时,该方法会基于对应的Class对象实现同步。
使用getClass()的返回值作为锁对象时,可能会导致开发人员误认为子类会基于基类进行同步。所以在编码过程中,应该使用明确的锁对象。

注:Object getClass()方法用于获取对象的运行时对象的类。

import java.util.ArrayList;
 
class RunoobTest {
    public static void main(String[] args) { 
    // getClass() with Object
    Object obj1 = new Object();
    System.out.println("obj1 的类为: " + obj1.getClass());
 
    // getClass() with String
    String obj2 = new String();
    System.out.println("obj2 的类为: " + obj2.getClass());
 
    // getClass() with ArrayList
    ArrayList<Integer> obj3 = new ArrayList<>();
    System.out.println("obj3 的类为: " + obj3.getClass());
    }
}
// 以上程序执行结果为:
// obj1 的类为: class java.lang.Object
// obj2 的类为: class java.lang.String
// obj3 的类为: class java.util.ArrayList 

ArrayList<Integer>和ArrayList<String>返回的都是class java.util.ArrayList

4、死锁

下列哪种操作可能带来死锁? C
A: lock(m1) lock(m2) unlock(m1) unlock(m2)
B: lock(m1) lock(m2) unlock(m2) lock(m2) unlock(m1) unlock(m2)
C: lock(m1) lock(m2) unlock(m1) lock(m1) unlock(m2) unlock(m1)
D: lock(m1) lock(m2) unlock(m1) unlock(m2) lock(m1) unlock(m1)

解析:前提条件是两个或多个进程都是按照相同的顺序来上锁、解锁的。

上一篇 下一篇

猜你喜欢

热点阅读