欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

<<并发编程实践>>学习笔记之什么叫锁

程序员文章站 2022-06-02 08:14:29
...
之前对并发了解的很少,觉得如果程序存在竞争条件,就直接加一个Synchronized就可以解决。发现越多很多源代码之后,发现别人加锁并不是简简单单的在方法上面加一个synchroized这么简单,先上一段代码.

public List<String> lists = Collections
.synchronizedList(new ArrayList<String>());

public synchronized boolean listIfAbsent(String str) {
boolean ifAbsent = lists.contains(str);
if (!ifAbsent) {
lists.add(str);
}
return ifAbsent;
}

public boolean listIfAbsent1(String str) {
synchronized (lists) {
boolean ifAbsent = lists.contains(str);
if (!ifAbsent) {
lists.add(str);
}
return ifAbsent;
}

}
public static void main(String[] args) {
final Test t = new Test();
new Thread() {
public void run() {

if (!t.lists.contains("a")) {
t.lists.add("a");
}
if (!t.lists.contains("b")) {
t.lists.add("b");
}
// t.lists.set(0, "chenliang");
System.out.println(t.lists);
}
}.start();

t.listIfAbsent1("a");
// t.listIfAbsent("b");

}


这里面有2个方法listIfAbsent和listIfAbsent1,一个应该算是悲观锁,还有一个是只是对list加锁,我之前以为只要对this加锁,该对象的所有的数据域都应该被保护,即使数据域全部被expose,但是经过测试,发现我错了,即使是同样的一个Test对象,当线程A调用listIfAbsent,线程B执行
t.lists.add("a"),这时候发生什么?我之前的理解就是,线程B是不能修改线程list中的数据域的。但事实上,结果并非如此,数据已经被破坏,导致线程会出现过期的数据。
这说明我根本没有理解什么叫锁。
事实上,锁就是对象的一个属性,一个Object对象都有对应的锁属性。我们对Test t这个对象加锁,但是他并不会去检查别的线程是否修改public lists属性。
我的理解就是,加锁的地方只是在方法上,但是这个Test t本身不代表锁。其他的线程仍然可以通过t去访问它其他的共有成员变量,就像这个LIST.如果是多个线程去调用这个上锁的方法的时候,才会出现互斥。
相关标签: