ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

类锁与对象锁的致命区别揭秘

类锁与对象锁的致命区别揭秘

4. 现在的人直接看懂的普通话书面语来说, 同步加锁的是对象, 而不是代码部分。因此, 当你的类里面存在一个同步方法的时候, 这个方法有可能被两个完全不同的线程同时执行。

实现这种情况的前提条件是, 每一个线程都必须自己创建一个这个类的实例,也就是每个线程持有的并不是同一个对象实例。所以, 只要满足每个线程各自创建独立该类的这种条件, 那么上述提到的那个同步方法的并发执行局面就会出现。

5. 不同的对象实例所对应的方法, 它们之间是不存在互相干扰的情况的。这也就是说, 其他的线程仍然能够同时地访问属于同一个类的另一个对象实例中的相关方法。

6. 关键字是不能继承的, 这一点大家要弄清楚, 也就是说, 当存在一个基类的方法 f(){}时, 在把它拿去给继承类的过程中, 它并不会自动变成继承类里面的 f(){}这种形式, 而是会发生一些变化, 变成了 f(){}的样子, 针对这种情况, 继承类这边是需要你来显式地去指定它的某一个方法就是那个方法。

7.当你去给一个全局静态的对象加锁, 或者说是给某个类的本身这个层次的东西加上同步保护机制的时候, 这种保护动作其实是对所有存在的对象实例都产生影响的, 也就是说是整个类层面的控制。

类锁举例

我们对那个属于全局范围的东西, 给它加上一个锁头。

1 public class MySynchronized extends Thread

2 {

3 private int val;

4

5 private static Object lock = new Object();

6

7 public MySynchronized(int v)

8 {

9 val = v;

10 }

11

12 public void printVal(int v)

13 {

14 synchronized (lock)

15 {

16 while (true)

17 {

18 System.out.println(v);

19 }

20 }

21 }

22

23 public void run()

24 {

25 printVal(val);

26 }

27 }

对整个类加锁:

1publicclassMySynchronizedextendsThread

2{

3privateintval;

4

5publicMySynchronized(intv)

6{

7 val =v;

8}

9

10publicvoidprintVal(intv)

11{

12synchronized(MySynchronized.class)

13{

14while(true)

15{

16System.out.println(v);

17}

18}

19}

20

21publicvoidrun()

22{

23printVal(val);

24}

25 }

另外的锁例子:

常量的这种特殊的地方, 在于它和同一个对象是紧密相关的。

public class MySynchronized extends Thread

{

private String name;

private String val;

public MySynchronized(String name, String v)

{

this.name = name;

val = v;

}

public void printVal()

{

synchronized (val)

{

while (true)

{

System.out.println(name + val);

}

}

}

public void run()

{

printVal();

}

public static void main(String args[])

{

MySynchronized f1 = new MySynchronized("Foo 1:", "printVal");

f1.start();

MySynchronized f2 = new MySynchronized("Foo 2:", "printVal");

f2.start();

}

}

这里所给出的, 是关于那个针对静态方法以及针对非静态方法的一个总结性的东西, 它俩之间存在着一个非常明显的区别。

/*

* 非静态方法:

* 给对象加锁(可以理解为给这个对象的内存上锁,注意 只是这块内存,其他同类对象都会有各自的内存锁),这时候

* 在其他一个以上线程中执行该对象的这个同步方法(注意:是该对象)就会产生互斥

* 静态方法:

* 相当于在类上加锁(*.class 位于代码区,静态方法位于静态区域,这个类产生的对象公用这个静态方法,所以这块

* 内存,N个对象来竞争), 这时候,只要是这个类产生的对象,在调用这个静态方法时都会产生互斥

*/

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进