1、synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){} 可以防止多个线程同时 访问这个对象的synchronized方法 (如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法 )。这时,不同的对象实例的 synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
总的来说,这种情况,锁就是这个方法所在的对象
2)是某个类的范围,synchronized static aStaticMethod{} 防止多个线程同时访问这个类中的synchronized static 方法 。它可以对类的所有对象实例起作用。此时锁就是这个class
2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
用法是: synchronized(this){/*区块*/},锁就是这个方法所在的对象 ;
3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
4、无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
每个对象只有一个锁(lock)与之相关联。
实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
1、理论上,每个对象都可以做为锁,但一个对象做为锁时,应该被多个线程共享,这样才显得有意义,在并发环境下,一个没有共享的对象作为锁是没有意义的 。假如有这样的代码:
- public class ThreadTest{
-
public void test(){
-
Object lock=new Object();
-
synchronized (lock){
-
- }
- }
- }
public class ThreadTest{
public void test(){
Object lock=new Object();
synchronized (lock){
//do something
}
}
}
lock变量作为一个锁存在根本没有意义,因为它根本不是共享对象,每个线程进来都会执行Object lock=new Object();每个线程都有自己的lock,根本不存在锁竞争。
2、为了保证银行账户的安全,可以操作账户的方法如下:
Java代码
public synchronized void add(int num) {
- balance = balance + num;
- }
-
public synchronized void withdraw(int num) {
- balance = balance - num;
- }
public synchronized void add(int num) {
balance = balance + num;
}
public synchronized void withdraw(int num) {
balance = balance - num;
}
每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,当一个被线程被唤醒 (notify)后,才会进入到就绪队列,等待cpu的调度。当一开始线程a第一次执行account.add方法时,jvm会检查锁对象account 的就绪队列是否已经有线程在等待,如果有则表明account的锁已经被占用了,由于是第一次运行,account的就绪队列为空,所以线程a获得了锁,执行account.add方法。如果恰好在这个时候,线程b要执行account.withdraw方法,因为线程a已经获得了锁还没有释放,所以线程 b要进入account的就绪队列,等到得到锁后才可以执行。
3、
Java代码
public class SyncBlock
- {
-
public void method1()
- {
-
synchronized(this)
- {
- … …
- }
- }
-
public void method2()
- {
-
synchronized(this)
- {
- … …
- }
- }
-
public synchronized void method3()
- {
- … …
- }
- }
public class SyncBlock
{
public void method1()
{
synchronized(this) // 相当于对method1方法使用synchronized关键字
{
… …
}
}
public void method2()
{
synchronized(this) // 相当于对method2方法使用synchronized关键字
{
… …
}
}
public synchronized void method3()
{
… …
}
}
在使用同一个SyncBlock类实例时,这三个方法只要有一个正在执行,其他两个方法就会因未获得同步锁而被阻塞。在使用synchronized块时要想达到和synchronized关键字同样的效果,必须将所有的代码都写在synchronized块中 ,否则,将无法使当前方法中的所有代码和其他的方法同步。
除了使用this做为synchronized块的参数外,还可以使用ClassName.class(本例为 SyncBlock.this )作为synchronized块的参数来达到同样的效果。
在内类(InnerClass)的方法中使用synchronized块来时,this只表示内类,和外类(OuterClass)没有关系。但内部类的非静态方法可以和外类的非静态方法同步 。如在内类InnerClass中加一个method4方法,并使method4方法和SyncBlock的三个方法同步,代码如下:
- public class SyncBlock
- {
- ...
-
class InnerClass
- {
-
public void method4()
- {
-
synchronized(SyncBlock.this)
- { ... }
- }
- }
- }
public class SyncBlock
{
...
class InnerClass
{
public void method4()
{
synchronized(SyncBlock.this)
{ ... }
}
}
}
该例中,InnerClass类的method4方法和SyncBlock类的其他三个方法同步,因此,method1、method2、method3和method4四个方法在同一时间只能有一个方法执行。
静态内部类可以直接创建对象new B.C();
如果内部类不是静态的,那就得这样
B b = new B();
B.C c = b.new C();
Synchronized块不管是正常执行完,还是因为程序出错而异常退出synchronized块,当前的synchronized块所持有的同步锁都会自动释放 。因此,在使用synchronized块时不必担心同步锁的释放问题。
4、sychronized关键字只和一个对象实例绑定
- class Test
- {
-
public synchronized void method()
- { }
- }
-
-
public class Sync implements Runnable
- {
-
private Test test;
-
-
public Sync(Test test)
- {
-
this.test = test;
- }
-
-
public void run()
- {
- test.method();
- }
-
-
public static void main(String[] args) throws Exception
- {
-
Test test1 = new Test();
-
Test test2 = new Test();
-
Sync sync1 = new Sync(test1);
-
Sync sync2 = new Sync(test2);
-
new Thread(sync1).start();
-
new Thread(sync2).start();
- }
- }
class Test
{
public synchronized void method()
{ }
}
public class Sync implements Runnable
{
private Test test;
public Sync(Test test)
{
this.test = test;
}
public void run()
{
test.method();
}
public static void main(String[] args) throws Exception
{
Test test1 = new Test();
Test test2 = new Test();
Sync sync1 = new Sync(test1);
Sync sync2 = new Sync(test2);
new Thread(sync1).start();
new Thread(sync2).start();
}
}
上面的代码建立了两个Test类的实例,因此,test1和test2的method方法是分别执行的。要想让method同步,必须在建立Sync类的实例时向它的构造方法中传入同一个Test类的实例。
Synchronized与ThreadLocal的区别:
ThreadLocal:http://yunqiang-zhang-hotmail-com.iteye.com/admin/blogs/1350437
一、
synchronized关键字主要解决多线程共享数据同步问题 。
ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题 。
ThreadLocal和Synchonized都用于解决多线程并发访问 。但是ThreadLocal与synchronized有本质的区别:
synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问 。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享 。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。
概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
分享到:
相关推荐
java多线程中synchronized关键字的用法 解压密码 www.jiangyea.com
Synchronized 是 Java 语言中的一个关键字,用于实现线程同步。它可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块。Synchronized 的核心原理是基于 Java 对象头和 Monitor 对象。 Java 对象头...
标题中的"java 多线程synchronized互斥锁demo"指的是一个示例,展示了如何在多线程环境下使用`synchronized`关键字创建互斥锁,确保同一时间只有一个线程可以访问特定的代码块或方法。 描述中的"一个多线程访问的同...
线程同步Synchronized,监视器monitor和锁lock的关系2---马克-to-win java视频
10.8-10.9马老师多线程笔记synchronized .md
Java中的多线程同步是通过对象锁机制来实现的,synchronized关键字正是这一机制的关键。它确保了在任何时刻,只有一个线程能够访问特定的共享资源,从而避免数据不一致的问题。本文将详细讲解Java线程的基本概念、...
一个简单的多线程代码示例,Java实现,用于实现同一时刻,只允许一个线程调用执行的代码块或类,即synchronized的如何使用(多线程实现),实现 Runnable
线程同步Synchronized,监视器monitor和锁lock的关系1---马克-to-win java视频
线程同步Synchronized,监视器monitor和锁lock的关系2---马克-to-win java视频
在Java程序中,多线程的运行安全可以通过使用synchronized关键字、Lock类、volatile关键字、CAS操作等实现。同时,Java也提供了线程池、Executor框架等机制来管理线程的创建和执行。 下面是Java并发编程面试题的...
Synchronized 是 Java 语言中用于解决多线程共享数据同步问题的关键字。它可以作为函数的修饰符,也可以作为函数内的语句,用于实现同步方法和同步语句块。在 Java 中,synchronized 关键字可以作用于 instance 变量...
Java 线程同步机制中 synchronized 关键字的理解 Java 的线程同步机制是为了解决多个线程共享同一片存储空间所带来的访问冲突问题。其中,synchronized 关键字是 Java 语言中解决这种冲突的重要机制。 ...
一、线程安全问题: 并发编程的原则:设计并发编程的目的是为了使程序获得更高的执行效率,但绝不能出现数据一致性(数据准确)问题,如果并发程序连基本的执行结果准确性都无法保证,那并发编程没有任何意义。 ...
3. 懒汉式(线程安全):在多线程环境中,使用`synchronized`保证实例化过程的线程安全,但可能导致性能下降。 ```java public class Singleton { private static Singleton INSTANCE; private Singleton() {} ...
Synchronized锁在Spring事务管理下,导致线程不安全。
在Java编程语言中,`synchronized`关键字是用于实现线程同步的重要机制,它确保了在多线程环境中的数据一致性与安全性。本篇将详细解析`synchronized`的关键特性和使用方法,帮助开发者深入理解如何在并发编程中有效...
Java中的`synchronized`关键字是用于实现线程同步的关键机制,它的主要目的是确保多个线程在访问共享资源时能保持数据的一致性和完整性,避免出现竞态条件和数据不一致的问题。在Java多线程编程中,`synchronized`有...
"基于Java synchronized同步锁实现线程交互" Java多线程能够提高CPU利用...因此,在使用Java多线程的场景中,请充分理解Java线程各状态之间的关系及其切换,并使用synchronized、wait()和notify()方法实现线程交互。