首先明确一点,同步方法本质上也是一个同步控制块(仅针对于锁定this的情况,如果同步控制块锁定的不是this,那么它是不能直接改写为同步方法的),区别在于同步方法的粒度是整个方法,而同步控制块的粒度可以是方法的一部分。
// 同步方法示例
public class Counter {
int count;
static int classCount;
public synchronized void bump() {
System.out.println("bump() starts");
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("bump() ends");
}
public static synchronized void classBump() {
classCount++;
System.out.println("classBump()");
}
}
// 同步方法可以等价地写成同步控制块
public class Counter {
int count;
static int classCount;
public void bump() {
synchronized (this) {
// ...
}
}
public static void classBump() {
synchronized (Counter.class) {
// ...
}
// 或者不用Counter.class,用Class.forName()
/**
try {
synchronized (Class.forName("Counter")) {
// ...
}
} catch (ClassNotFoundException e) {
e.printStack();
}
*/
}
}
从这个例子可以看出,Class锁(针对static方法)和Object锁(针对非static方法)是两种锁。从实验的结果来看,这两种锁是不冲突的,即:假设有Counter c = new Counter();,如果Thread A调用c.bump()方法,那么synchronized(this)只是锁定了c这个对象,Thread B可以无所顾忌地调用Counter.classBump()(或者c.classBump()也可以),不用等待Thread A释放c的锁。如:
public class MultiThreadTest8 {
public static void main(String[] args) {
final Counter c = new Counter();
Thread t1 = new Thread(
new Runnable() {
@Override public void run() {
c.bump();
}
}, "Runner 1");
Thread t2 = new Thread(
new Runnable() {
@Override public void run() {
//Counter.classBump();
c.classBump();
}
}, "Runner 2");
t1.setPriority(Thread.NORM_PRIORITY + 2);
t1.start();
t2.start();
// output:
/**
bump() starts
classBump()
bump() ends
*/
}
}
不过一旦Thread A调用c.bump(),锁定了c,那么Thread B就不能调用c.bump()了,c中的其他同步方法或是同步控制块Thread B也不能访问,只有等到Thread A释放c的锁(即c.bump()同步部分执行完)。Counter的非同步方法不受锁的限制,即使Thread A锁定了c,Thread B也可以随意访问c的非同步方法。
p.s. 这里说锁定一个对象,并不是说属性不能访问,锁定对象只是锁定同步方法或是同步控制块,使同步方法或是同步控制块的执行不会被其他线程打断(可以理解为:锁定方法到一个线程)。如果有一个同步方法去修改某个字段,此时是可以有另一个非同步方法也去修改这个字段,这样仍然有可能产生数据不一致的情况。
p.s.
synchronized关键字可以放在类的前面,表示类中的所有方法都是同步方法。
分享到:
相关推荐
Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...
java多线程中synchronized关键字的用法 解压密码 www.jiangyea.com
Java多线程(Synchronized+Volatile+JUC 并发工具原理+线程状态+CAS+线程池)
Java多线程学习(一)Java多线程入门Java多线程学习(二)synchronized关键字(1)Java多线程学习(二)synchronized关键字(2
一个多线程访问的同一个资源,java synchronized互斥锁的用法,android和此用法一致。
Java多线程synchronized关键字详解(六)共5页.pdf.zip
本资源致力于向您介绍 Java 并发编程中的线程基础,涵盖了多线程编程的核心概念、线程的创建和管理,以及线程间通信的基本方法。通过深入学习,您将建立扎实的多线程编程基础,能够更好地理解和应用多线程编程。 多...
2. Java多线程学习(二)synchronized关键字(1) 3. Java多线程学习(二)synchronized关键字(2) 4. Java多线程学习(三)volatile关键字 5. Java多线程学习(四)等待/通知(wait/notify)机制 6. Java多...
主要介绍了Java 多线程synchronized关键字详解(六)的相关资料,需要的朋友可以参考下
单线程程序 多线程程序 Thread类的run方法和start方法 线程的启动 线程的启动(1)——利用Thread类的子类 线程的启动(2)——利用Runnable接口 线程的暂时停止 线程的共享互斥 synchronized方法 synchronized阻挡 ...
并发编程原理学习:synchronized关键字.doc
你还在用synchronized?线程安全相关知识深入剖析
多线程注意:wait()方法的调用要有判定条件常用 while () obj.wait(timeout, nanos); ... // Perform action appropriate to condition } synchronized会影响共享数据,但对其他语句的执行不会有规律了!
包括java的Thread类,同步块(synchronized),可重入锁,Object方法以及对象监视器等内容。
1.讲解了Java多线程的基础, 包括Thread类的核心API的使用。2.讲解了在多线程中对并发访问的控制, 主要就是synchronized的使用, 由于此关键字在使用上非常灵活, 所以书中用了很多案例来介绍此关键字的使用, 为...
Java线程(二):线程同步synchronized和volatile 详细讲解Java 同步的原理技术资料
1、在系统中对访类要使用多线程进行访问; 2、在该类中有 类变量,或者是 在类的方法中有访问公共资源(如一个外部文件的读写)。 同步锁锁定的内容是什么? 无论你将Synchronized加在方法前还是加在...
Synchronized是Java中解决并发问题的一种常用的方法,也是简单的一种方法。Synchronized的作用主要有三个:(1)确保线程互斥的访问同步代码(2)保证共享变量的修改能够及时可见(3)有效解决重排序问题。从语法...
java锁机制Synchronized java锁机制Synchronized java锁机制Synchronized java锁机制Synchronized