synchronized
用到不同地方对代码产生的影响:
假设
P1
、
P2
是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,
P1
、
P2
就都可以调用它们。
1.
把
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
.将
synchronized
作用于
static
函数,示例代码如下:
Class Foo
{
public synchronized static void methodAAA()
//
同步的
static
函数
{
//….
}
public void methodBBB()
{
synchronized(Foo.class)
//
class literal(
类名称字面常量
)
}
}
代码中的
methodBBB()
方法是把
class literal
作为锁的情况,它和同步的
static
函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(
Class
,而不再是由这个
Class
产生的某个具体对象了)。
记得在《
Effective Java
》一书中看到过将
Foo.class
和
P1.getClass()
用于作同步锁还不一样,不能用
P1.getClass()
来达到锁这个
Class
的目的。
P1
指的是由
Foo
类产生的对象。
可以推断:如果一个类中定义了一个
synchronized
的
static
函数
A
,也定义了一个
synchronized
的
instance
函数
B
,那么这个类的同一对象
Obj
在多线程中分别访问
A
和
B
两个方法时,不会构成同步,因为它们的锁都不一样。
A
方法的锁是
Obj
这个对象,而
B
的锁是
Obj
所属的那个
Class
。
小结如下:
搞清楚
synchronized
锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。
还有一些技巧可以让我们对共享资源的同步访问更加安全:
1.
定义
private
的
instance
变量
+
它的
get
方法,而不要定义
public/protected
的
instance
变量。如果将变量定义为
public
,对象在外界可以绕过同步方法的控制而直接取得它,并改动它。这也是
JavaBean
的标准实现方式之一。
2.
如果
instance
变量是一个对象,如数组或
ArrayList
什么的,那上述方法仍然不安全,因为当外界对象通过
get
方法拿到这个
instance
对象的引用后,又将其指向另一个对象,那么这个
private
变量也就变了,岂不是很危险。
这个时候就需要将
get
方法也加上
synchronized
同步,并且,只返回这个
private
对象的
clone()
――这样,调用端得到的就是对象副本的引用了。
分享到:
相关推荐
`synchronized`关键字可以修饰方法或用作代码块,其主要作用是控制对共享资源的并发访问,防止数据不一致和竞态条件。当一个线程进入`synchronized`代码块或方法时,其他试图进入同一块的线程将被阻塞,直到持有锁的...
但是,这个对象所属的 Class 所产生的另一对象 P2 却可以任意调用这个被加了 synchronized 关键字的方法。 在以下代码中: public void methodAAA(){ synchronized (this) { //….. } } this 指的是调用这个...
非线程安全指多个线程同时对同一个对象的同一个实例变量进行读改操作,改变现有的值,此时会产生数据的脏读,导致数据不同步的情况,进而影响了程序的执行流程。 六、synchronized 同步锁概念及使用方法 ...
除了被用于方法上,synchronized 关键字也可以被用于代码块中,以实现对共享资源的互斥访问控制。例如: ```java public class MyClass { public void myMethod() { synchronized (this) { // ... } } } ``` 在...
使用 Synchronized 代码块可以缩小同步的影响范围,提高程序的运行效率。同时,Synchronized 代码块也可以在一定时期内霸占某个对象的钥匙,避免其他线程访问该对象的上锁房间。 Synchronized 的使用原则 ...
通过在方法或代码块上使用`synchronized`,可以确保同一时间只有一个线程能访问这些代码区域,从而有效避免了多线程环境下的数据竞争和不一致性问题。 #### 二、synchronized的作用机制 `synchronized`主要通过对象...
Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...
- **原子性**:`synchronized`保证了在执行代码块或方法时的原子性,这意味着整个代码块或方法要么全部被执行,要么全部不被执行。 ##### 2. volatile关键字 `volatile`关键字用于标记那些在多线程环境中可能会被...
`m4t1()`使用了同步代码块,而`m4t2()`最初没有使用同步,之后进行了修改以观察不同情况下的执行结果。 ```java public class Thread2 { public void m4t1() { synchronized (this) { int i = 5; while (i-- > ...
1. **同步代码块**:可以通过`synchronized`关键字来声明同步代码块,即通过指定对象锁来实现同步。 ```java synchronized (object) { // 需要同步执行的代码 } ``` - 这种方式中,`object`对象作为锁,任何...
Synchronized既可以对代码块使用,也可以加在整个方法上。 关键是,不要认为给方法或者代码段加上synchronized万事大吉,看下面一段代码: class Sync { public synchronized void test() { System.out...
- **代码块同步:** 也可以使用`synchronized`关键字来同步代码块,这样可以更细粒度地控制同步范围,提高程序性能。 ```java public void method() { synchronized (object) { // 代码块 } } ``` 这里的`object...
本文将深入探讨`synchronized`的几种使用示例,包括方法加锁、代码块加锁(针对`this`和对象)以及静态方法加锁。 1. **方法加锁** 当在实例方法前使用`synchronized`关键字时,它会锁定当前对象的监视器,只有...
`synchronized`提供了一种机制,使得在多线程环境中,对特定代码或方法的访问变得有序和安全。 首先,`synchronized`可以应用于两种情况:同步方法和同步代码块。同步方法是通过在方法声明前加上`synchronized`...
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
通过同步方法和同步语句块,我们可以控制对共享数据的访问,并通过类锁和对象锁区分不同级别的锁定粒度。结合等待/通知机制,可以实现更复杂的线程协作。理解并熟练使用`synchronized`,是编写健壮的多线程Java程序...
通过使用`synchronized`,可以确保同一时间只有一个线程能够执行特定代码块,从而防止数据的不一致性和线程安全问题。下面将详细介绍`synchronized`的用法及其在不同场景下的应用。 1. 同步方法: 当`synchronized...
`@synchronized`关键字是Apple提供的一种简便的同步机制,它可以帮助开发者确保在多线程环境下对共享资源进行原子性操作,防止数据竞争问题。本文将深入探讨`@synchronized`的工作原理、特点以及使用时需要注意的...
- 从Java 5开始,JVM对`synchronized`进行了很多优化,如偏向锁、轻量级锁、自旋锁等,使得在低负载情况下,同步操作的性能得到了显著提升。 9. **示例代码分析**: 根据提供的文件名,`GenerateCode.java`可能...
在Java编程语言中,同步代码块(synchronized blocks)是一种重要的多线程控制机制,用于保证线程安全,防止数据的不一致性。本压缩包包含了两个示例代码——Example12.java和Example13.java,它们是针对同步代码块...