关于原子
嗯,为什么要加锁?相信有点基础的童鞋都很清楚。在多线程情况下调用方法主要会出现两类问题 --原子性和非原子性!那他们各自会在神马情况下出现捏?
举一个《thinking in java》第四版中的例子。有一个EvenGenerator类,它的next()方法用来生成偶数。如下:
public class EvenGenerator {
private int currentValue = 0;
private boolean cancled = false;
public int next() {
++currentValue; //危险!
++currentValue;
return currentValue;
}
public boolean isCancled() {
return cancled;
}
public void cancle() {
cancled = true;
}
}
另外有一个EvenChecker类,用来不断地检验EvenGenerator的next()方法产生的是不是一个偶数,它实现了Runnable接口。
public class EvenChecker implements Runnable {
private EvenGenerator generator;
public EvenChecker(EvenGenerator generator) {
this.generator = generator;
}
@Override
public void run() {
int nextValue;
while(!generator.isCancled()) {
nextValue = generator.next();
if(nextValue % 2 != 0) {
System.out.println(nextValue + "不是一个偶数!");
generator.cancle();
}
}
}
}
然后创建两个EvenChecker来并发地对同一个EvenGenerator对象产生的数字进行检验。
public class Test {
public static void main(String[] args) {
EvenGenerator generator = new EvenGenerator();
Thread t1 = new Thread(new EvenChecker(generator));
Thread t2 = new Thread(new EvenChecker(generator));
t1.start();
t2.start();
}
}
显然,在一般情况下,EvenGenerator的next()方法产生的数字肯定是一个偶数,因为在方法体里进行两次”++currentValue”的操作。但是运行这个程序,输出的结果竟然像下面这样(并不是每次都是这个一样的结果,但是程序总会因这样的情况而终止):
849701不是一个偶数!
错误出在哪里呢?程序中有“危险”注释的哪一行便可能引发潜在的错误。因为很可能某个线程在执行完这一行只进行了一次递增之后,CPU时间片被另外一个线程夺去,于是就生产出了奇数。
原子性(atomicity)
具有原子性的操作被称为原子操作。原子操作在操作完毕之前不会线程调度器中断。在Java中,对除了long和double之外的基本类型的简单操作都具有原子性。简单操作就是赋值或者return。比如”a = 1;”和 “return a;”这样的操作都具有原子性。但是在Java中,上面例子中的类似”++currentValue;”这样的操作不具有原子性,所以如果add方法不是同步的就会出现难以预料的结果。在某些JVM中”++currentValue;”可能要经过这样四个步骤:
1.从内存得到currentValue的值
2.第一次+currentValue
3.第二次+currentValue
4.把currentValue写回内存
上面会出现奇数的情况就是第一次+currentValue完成的时候,还没来得及往内存中写数据。CPU的时间片被另一个线程占用,当那个线程使用完CPU切换回来的时候再来运行+currentValue,就会出现奇数了!
解决以上问题的方法无疑就是同步
关于synchronized
1.方法上加synchronized 是给整个类加锁。synchronized(Object){}是给object对象加锁。相对而言各有各的用处,但是,不到迫不得已坚决不用synchronized加锁!
步的代价:首先,同步化的方法有些额外的成本。进入同步化方法的程序会查询锁等性能上的损耗。其次,同步化方法会强制线程队列排队等着执行方法。最后,同步化很可能会导致死锁!!!!!!!!!!!!!!!!!!
同步的死锁
在java中,死锁是一件很恐怖的事情!因为java根本没有处理死锁的机制,他甚至不会知道死锁的发生!
下面来看一下可以如何导致死锁
head firs java 中的说法
两个线程和两个对象
线程A foo
线程B bar
1.线程A进入对foo对象设定同步化的方法
2.线程B进入对bar对象设定同步化的方法,线程B接着尝试要进入A正在执行的方法。所以B一直等着。
3.线程A醒来尝试调用线程B正在执行的方法,但拿不到钥匙,所以只好等着
A一直等着B的bar钥匙,B却也在等着A的foo钥匙。两个线程就这样僵持着!
分享到:
相关推荐
Java多线程面试问题和答案总结 Java多线程是一种高级的编程技术,能够充分发挥多核CPU的优势,防止阻塞,简化模型建立,提高程序的效率和可维护性。下面是40个Java多线程面试问题和答案的总结,涵盖了多线程的基本...
书中包含Java线程的介绍导读、12个重要的线程设计模式和全书总结以及丰富的附录内容。第一章相关线程设计模式的介绍,都举一反三使读者学习更有效。最后附上练习问题,让读者可以温故而知新,能快速地吸收书中的...
总结起来,"Java多线程实例图形版"是一个结合理论与实践的教学资源,通过“哲学家就餐问题”这一经典案例,帮助开发者理解多线程的基本概念、并发问题以及解决策略。通过学习这个实例,不仅可以掌握Java多线程编程的...
个人关于java基础多线程的思维导图总结。0积分下载。如果认为有帮助,请关注点赞,日后还有更多免费资源。
看完《think in java》多线程章节,自己写的多线程文档,还结合了其他的相关网络资料。 线程 一. 线程池 1)为什么要使用线程池 2 2)一个具有线程池的工作队列 3 3)使用线程池的风险: 4 4)有效使用线程池的原则 5...
目录: 漫谈UML Introduction 1 Java语言的线程 Introduction 2 多线程程序的评量标准 第1章 Single Threaded Execution——能通过这座桥的,只有一...附录C Java线程的优先级 附录D 线程相关的主要API 附录E 参考文献
在IT行业中,多线程是程序并发执行的一种方式,它极大地提高了系统资源的利用率和程序...在学习过程中,可以参考"多线程基础总结01.bmp"和"多线程基础总结01.mmap"等文件,它们可能提供了更为详细和直观的结构化知识。
Java 培训个人总结 Java 语言作为一款强大的、跨平台的高级编程语言,广泛应用于网络、桌面、分布式及嵌入式领域。其旺盛的生命力吸引了无数开发者投身于 Java 学习。对于初学者,Java 技术入门至关重要,这一步...
- Java支持多线程编程,可以通过实现Runnable接口或继承Thread类创建线程。 - 线程间的通信和同步机制包括synchronized关键字、wait()、notify()和notifyAll()方法。 9. **网络编程**: - Java提供了Socket和...
这份"JAVA学习历程(基础知识个人总结1,2,3)"的文档集合,显然是一位热情的学习者在探索JAVA世界时,逐步积累并整理出的心得体会。这些文档可能包含了从入门到进阶的各类关键知识点,旨在帮助读者构建全面的JAVA...
Java基础是编程学习的重要起点,本篇将对Java的...这为后续深入学习Java面向对象特性、异常处理、集合框架、IO流、多线程等内容打下了坚实的基础。通过不断地实践和学习,开发者能逐步熟练运用Java解决各种复杂问题。
) 本文档是基于毕向东老师的java基础视频和张孝祥老师的高薪技术视频和银行管理系统以及交通灯管理系统的视频所做的笔记。...(此文档全手打,个人总结也许有不到位或者失误的地方,欢迎您指正。非常感谢~)
### Java多线程入门 #### 一、进程与线程的区别 在理解Java中的多线程之前,我们先来看看进程和线程之间的区别。 - **进程**:进程是程序的一次执行过程,它是系统进行资源分配和调度的一个独立单位。每个进程都...
【Java培训个人总结】 在2022年的Java培训中,我深入地学习了这门广泛应用于各种领域的高级编程语言。Java以其跨平台的特性,无论是开发桌面应用程序、网络服务,还是分布式系统和嵌入式设备,都有其独特的优势。在...
1. **Java总结.doc**:这可能是对Java语言核心概念的全面概述,包括但不限于变量、数据类型、运算符、流程控制(if、switch、for、while)、类与对象、封装、继承、多态等。此外,还可能涵盖异常处理、文件I/O、集合...
这份"2022最新Java个人面试总结及整理"包含了开发者在求职过程中可能会遇到的关键知识点,旨在帮助面试者更好地准备和理解Java技术栈的核心内容。以下是对这些知识点的详细阐述: 1. **基础语法**:Java的基础语法...
Java 培训个人总结 Java 语言作为一款强大的、跨平台的高级编程语言,其广泛应用在网络、桌面、分布式计算及嵌入式领域,显示出了极强的生命力。对于想要进入IT行业的人员而言,掌握Java语言是至关重要的。在2022年...
【Java培训个人总结】 在Java培训过程中,我们深入学习了Java语言的核心概念和技术,包括面向对象编程、异常处理、集合框架、多线程、IO流、网络编程等基础内容。这些知识点构成了Java开发的基础,是成为一名合格...
### Java线程超时控制实现详解 #### 一、引言 在开发过程中,经常会遇到需要对线程执行时间进行限制的情况,例如与远程数据库的交互或网络数据的下载等耗时操作。为了提高程序的健壮性和用户体验,合理地控制这些...