本文共 1446 字,大约阅读时间需要 4 分钟。
当多个线程同时对某一个数据区或内存位置进行操作时,如果不施加任何措施,很可能造成数据操作混乱.
如同数据库中的 脏读,不可重复读和幻读等情况.当只有一个线程访问数据时,数据竞争基本不会存在;只有多线程同时访问数据时,才会发生数据竞争.
数据竞争问题是有至少两个同时执行的线程访问同一个内存位置并且至少有一个线程尝试写入数据而引起的问题. 为了避免数据竞争,通常需要在程序中加入同步机制,以保证数据访问的正确性.有些同步机制(如:锁)可以保证数据在某一时间内只有一个线程访问, 有些同步机制(如:软件事务性内存)可以让数据由多个线程操作,虽然多线程同时访问,但是会保证最早提交的数据有效,其他的数据操作要回滚.某一段被多个线程共享的数据区域,线程必须对它进行互斥访问;线程中访问共享数据的那段代码被称为临界区(Critical Section).线程进入临界区需要遵循一定的原则.
为了帮助程序员实现临界区,Java 提供了同步机制.当一个线程试图访问临界区时,同步机制会判断当前是否有其他线程正在使用临界区.
在 Java 语言中,监视器(Monitor)具有如下特征:
当线程请求某一种资源时,如果线程的请求得不到响应,线程可以采用多种方式来决定接下来要采取的动作.
1,线程可以采用一直尝试的方式,在每次请求资源得不到得不到满足的情况下,下一次依然继续请求,直到请求获得满足.采用这种方式的线程处于一种非阻塞状态,如果资源被占用的时间过长,这种方式必然会导致CPU资源的浪费. 2,另外一种方式:线程并不是一直等待,而是被阻塞;这样CPU的资源可以让出来执行一些其他的操作.线程被阻塞表示线程可能被CPU挂起,等待某一时间后,再去尝试获取资源.在程序设计过程中,一般要先保证程序的正确性,其次才是提高程序的性能.
在传统的串行执行的程序中,程序往往有一个固定的执行次序,对于数据的访问操作也是有顺序的. 然而,在多线程程序中,必须保证数据被多个线程操作是安全的.一个对象是否是线程安全的?
当多线程同时访问某个类时,不管线程之间如果交替执行,总能够得到正确的执行结果,则称这个类是线程安全的;否则是线程不安全的.要编写线程安全的代码,需要特别注意哪些共享的(Shared)和可变的(Mutable)数据或状态的操作.共享意味着变量可以被对个线程所访问,可变意味着变量的值在其生命周期内会发生变化.
线程安全的代码需要采用同步机制来控制对于共享的或者可变的变量的访问,特别是多个线程中至少存在一个写操作的情况下.Java 工具集合中提供的类有些是线程安全的(如:HashTable),有的则不是(如:HashMap).一般在线程安全的类中已经封装了必要的同步控制机制,因此不必进一步采取同步控制措施.
转载地址:http://nyazi.baihongyu.com/