synchronized用到不同地方对代码产生的影响:
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。
【1:锁定方法、this】. 把synchronized当作函数修饰符时,示例代码如下:
Public synchronized void methodAAA(){
}
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。
上边的示例代码等同于如下代码:
public void methodAAA(){
synchronized (this) { // (1)
}
}
(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法, 而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱
【2:锁定对象引用、普通变量】.同步块,示例代码如下:
public void method3(SomeObject so){
synchronized(so){
//…..
}
}
这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:
class Foo implements Runnable{
private byte[] lock = new byte[0]; // 特殊的instance变量
Public void methodA(){
synchronized(lock) { //… }
}
}
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
【3:锁定static方法、类名称字面常量】.将synchronized作用于static 函数,示例代码如下:
Class Foo
{
public synchronized static void methodAAA() { // 同步的static 函数
}
public void methodBBB(){
synchronized(Foo.class) // class literal(类名称字面常量)
}
}
代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的, 取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。
【注意】
要并发不一定多线程,多线程有可能涉及到同步。
多线程主要是不能保存线程调度的先后顺序导致数据可能会乱,所以要考虑同步。
在多线程环境中,当各线程不共享数据的时候,那么一定是线程安全的。问题是这种情况并不多见,在多数情况下需要共享数据,这时就需要进行适当的同步控制了。
搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。
线程:考虑线程的方法的使用
当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
synchronized后面必须跟一个对象, 这个对象就是监视器, 第一个线程进入synchronized体时就锁定了这个监视器, 同一时间只能有一个线程能锁定监视器, 所以当第二个线程试图进入synchronized体时就会阻塞在那里, 直到第一个线程出synchronized体后就解锁这个监视器, 第二个线程才有可能获得这个监视器, 是有可能而不是一定,
分享到:
相关推荐
`HashMap`在不同JDK版本间可能存在差异,例如在JDK 7及之前,`HashMap`是非线程安全的,而在JDK 8中进行了优化,引入了红黑树提高性能。`ConcurrentHashMap`是线程安全的Map实现,适用于多线程环境下的并发访问。 ...
线程安全意味着当多个线程同时访问一个对象或数据时,对象的状态能够保持一致性和完整性,不会因为并发导致数据的不一致。在描述中提到,线程安全的对象是那些在多线程环境中,其状态(即数据)能够得到正确保护的...
为了安全地访问共享数据,可以使用锁(如`lock`关键字)或监视器(`Monitor`类),以确保同一时间只有一个线程能访问这部分代码。此外,`volatile`关键字可用于确保多线程环境中的数据一致性,确保所有线程都能看到...
它教导我们如何通过条件等待和信号机制实现线程间的协同工作,以及如何利用锁对象来保证数据的正确性和线程安全。通过学习这个示例,开发者能够更好地理解和运用Java的并发编程技术,提高多线程应用程序的设计和性能...
线程安全指的是当多个线程访问一个对象时,如果这个对象能保持内部状态的完整性,那么我们就说这个对象是线程安全的。在这个场景下,"往盘子里放鸡蛋"和"向盘子里取鸡蛋"可以被看作是两个并发操作,它们涉及到共享...
VC++中实现线程锁的方法多种多样,包括临界区(Critical Section)、互斥量(Mutex)、事件对象(Event)等。在提供的文件列表中,如`RWLock.cpp`,可能涉及到了读写锁(Read-Write Lock),这是一种更为复杂的线程...
2. 使用线程安全的对象:使用线程安全的对象,如 Vector、Hashtable 等,而不是 ArrayList、HashMap 等。 3. 使用锁机制:使用锁机制,如 synchronized 关键字,可以锁定某个对象,以避免多个线程同时访问同一个对象...
本主题将深入探讨多线程的使用以及线程锁的两种主要实现方式: synchronized关键字和ReentrantLock。 一、多线程基础 1. 线程创建: - 继承Thread类:创建一个新的类,该类继承自Thread类,并重写run()方法。然后...
`BlockingQueue`接口定义了一系列的方法来支持线程安全的操作: - **add(anObject)**: 将`anObject`添加到`BlockingQueue`中,如果队列当前可以容纳该对象,则返回`true`,否则抛出异常。 - **offer(anObject)**: ...
可以抽取资源类,共享同一个资源对象,这样可以避免线程安全问题。 三、线程同步机制 线程同步机制是解决线程安全问题的一种方法。常见的线程同步机制有:同步块(Synchronized Block)、同步方法(Synchronized ...
为了确保线程安全,我们需要在记录日志时进行同步控制,例如使用互斥锁(mutex)。 3. **日志输出函数**:这是核心功能,它接收日志消息并将其写入日志文件。在多线程环境中,我们需要确保每次只有一个线程可以执行...
Java多线程编程中,线程安全问题是常见的挑战,特别是在并发环境下,多个线程可能会同时访问和修改同一份共享资源,导致数据不一致。为了解决这个问题,Java提供了同步机制,其中一种常用的方式就是同步代码块...
这时,如果没有正确的同步机制,就可能出现线程安全问题。例如,如果一个线程正在读取数组元素,而另一个线程同时在修改这个元素,可能会导致数据不一致。为了解决这个问题,Java提供了synchronized关键字来实现线程...
- **同步机制**:通过`synchronized`关键字、`ReentrantLock`等来控制对共享资源的访问,确保线程安全。 5. **解决单例模式中的懒汉式的线程安全问题**: - 使用双重检查锁定(DCL)模式。 - 使用枚举方式实现单例...
本文将深入探讨在多线程环境中使用List时遇到的非线程安全问题,并提供相应的解决方案和最佳实践。 List是.NET框架中常用的一个动态数组,它提供了方便的增删改查操作。然而,List并未设计为线程安全的容器,这意味...
本篇文章将深入探讨Python中的多线程安全问题以及如何使用锁(Lock)和可重入锁(RLock)来解决这些问题。 首先,我们要理解什么是线程安全。线程安全是指在多线程环境下,一个函数或方法被多个线程调用时,不会...
线程安全是指在多线程环境下,代码和数据结构不受破坏的能力,确保了共享资源的正确性。 此外,`Thread.Join`方法用于等待指定线程完成,而`IsAlive`属性可以检查线程是否仍在运行。`ThreadPriority`属性可以设置...