之前对并发了解的很少,觉得如果程序存在竞争条件,就直接加一个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.如果是多个线程去调用这个上锁的方法的时候,才会出现互斥。
分享到:
相关推荐
### Java并发编程实践笔记知识点详解 #### 一、保证线程安全的方法 1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。...
这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...
Java并发编程实践中的线程池是一个关键的概念,它在多线程编程中扮演着至关重要的角色,有效地管理和调度线程资源,以提高系统的性能和效率。线程池通过复用已存在的线程来减少线程的创建和销毁开销,避免了频繁的上...
JAVA并发编程实践-构建执行程序块-学习笔记 JAVA并发编程实践是指在JAVA编程语言中,使用多线程、并发编程来实现高效、可靠的程序执行。构建执行程序块是指在并发编程中,使用线程安全的类来管理状态,以确保程序的...
在并发编程中,有三种常见的锁策略:乐观锁、悲观锁和自旋锁。乐观锁假设冲突很少发生,因此在读取数据时不加锁,只有在更新时才会检查数据是否被其他线程修改过。悲观锁则假设冲突频繁,所以在读取数据时立即加锁,...
本篇将基于"并发编程之一 日常学习笔记"这一主题,深入探讨并发锁机制,特别是对Java中的`synchronized`关键字的深入理解。 并发编程的核心挑战在于正确地管理共享资源,避免数据竞争和死锁等问题。Java的`...
总的来说,Java并发编程实践中的任务执行是一个涉及线程调度、线程池管理、任务生命周期控制、结果处理等多个方面的复杂主题。理解和掌握这些概念和技术,能够帮助开发者编写出更加高效、可靠的并发程序。
通过阅读"Go语言学习笔记",你可以建立起对Go语言全面的认知,然后借助"Go并发编程实战"来深化对并发编程的理解,结合实际编写示例程序,将理论知识转化为实践经验。 在学习过程中,建议先从基础语法开始,掌握变量...
本压缩包中包含的"Example"文件夹,极有可能是《JAVA学习笔记》一书中的实例源代码,旨在帮助读者深入理解书中讲解的Java编程原理和实践技巧。下面我们将对这些源代码进行详细解读,以便更好地掌握Java编程。 1. **...
MFC的DLL支持可以帮助减少程序的内存占用,ActiveX控件则允许开发可重用的组件,多线程则可以实现并发执行,提升程序响应速度。 通过阅读《MFC深入浅出》,读者不仅可以掌握MFC的基本用法,还能了解到许多实际开发...
"JUC并发编程学习笔记(硅谷)"很可能包含了关于Java并发工具集(Java Util Concurrency, JUC)的深入理解和实战经验。JUC是Java标准库提供的一套强大的并发处理工具,它极大地简化了多线程编程,提高了程序的可读性...
11. **案例分析与实战**:笔记可能包含实际的并发编程案例,帮助读者更好地将理论知识应用到实践中。 通过深入学习这份"Java并发实践-学习笔记",开发者能够提升自己在处理多线程和并发问题上的能力,从而设计出更...
标题“多线程与高并发编程笔记、源码等”表明了资源的核心内容,涵盖了多线程和高并发编程的理论与实践。多线程允许一个应用程序同时执行多个任务,而高并发则指系统能够处理大量并发请求的能力。这两个概念在现代...
在Java并发编程中,线程的关闭和取消是一项重要的任务,因为不正确的处理可能导致数据不一致、资源泄漏等问题。在Java中,强制停止线程并不是一个推荐的做法,因为这可能会导致系统状态的不稳定。传统的`Thread.stop...
使用java.util.concurrent类库构造安全的并发应用程序的基础。共享其实就是某一线程的数据改变对其它线程可见,否则就会出现脏数据。
- 并发编程:学习多线程和并发控制,提高程序效率。 - 高级特性:如Lambda表达式、右值引用、自动类型推断(auto)等现代C++特性。 **四、C++的实践** 理论学习是基础,但实践才能真正巩固知识。通过编写小程序、...
本笔记主要聚焦于Java平台上的并发编程,旨在帮助开发者理解和掌握相关的核心概念、工具和最佳实践。 一、线程与进程 在并发编程中,我们首先需要理解“线程”和“进程”的概念。进程是操作系统分配资源的基本单位...
**并发编程笔记** 在计算机科学中,并发编程是让多个任务在同一时间运行的技术,它可以显著提升系统的效率和响应性。特别是在多核处理器和分布式系统中,并发编程是必不可少的技能。本笔记主要针对Java平台,深入...