java线程之——synchronized的注意细节
我在学习synchronized的时候,十分好奇当一个线程进入了一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
然后就做了个实验(实验代码最后贴出),最后得到了如下结论。
现在分两种情况来讨论:1.当前线程调用的是synchronized普通方法(相对于static方法);2.当前线程调用的是synchronized static方法。
1.当前线程调用的是synchronized普通方法(相对于static方法)时,其它线程是否可进入此对象的其它方法:
1)其它方法是加了synchronized的普通方法,不能;
2)其它方法是没加synchronized的普通方法,能;
3)其它方法是synchronized的static方法,能;
4)其它方法是没加synchronized的static方法,能。
2.当前线程调用的是synchronized static方法,其它线程是否可进入此对象的其它方法:
1)其它方法是加了synchronized的普通方法,能;
2)其它方法是没加synchronized的普通方法,能;
3)其它方法是synchronized的static方法,不能;
4)其它方法中有synchronized(xxx.class)的,不能;
5)其它方法是没加synchronized的static方法,能。
其实只要明白了普通方法加synchronized的本质是给对象的this加了对象锁,上面的结论就不难理解了,
其中不管static方法是否加synchroized,只要锁的是this,即当前对象,而不是当前类(XXX.class),就可以执行;
而给当前类加锁时,除了同步的static方法不能调用外,其它的都可以。
实验代码如下:
package javaBase; public class JB_052_Synchronized {
public static void main(String[] args) {
Resource_052 rs = new Resource_052(); Thread t1 = new Thread(new Thread1_052(rs)); //调用synchronized方法的线程
Thread t0 = new Thread(new Thread0_052(rs)); //调用普通方法的线程
Thread t2 = new Thread(new Thread2_052(rs)); //调用另一个synchronized方法的线程
Thread t3 = new Thread(new Thread3_052(rs)); //调用synchronized static 方法的线程
Thread t4 = new Thread(new Thread4_052(rs)); //调用static方法的线程 Thread t5 = new Thread(new Thread5_052(rs)); //调用锁class方法的线程 t1.start(); //调用了synchronized方法
try{
System.out.println("调用synchronized方法的thread1启动后主程序等待2秒,确保在其它线程执行之前thread1获得对象锁");
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
t0.start(); //调用了普通方法 //可以
t2.start(); //调用了另一个synchronized方法 //不行
t3.start(); //调用了synchronized static 方法 //可以
t4.start(); //调用了static方法 //可以 //锁class
try{
System.out.println("主程序等待10秒,等前面的线程除thread1和被阻塞的线程外都执行完成,后面的代码将做锁class测试....");
Thread.sleep(10000);
System.out.println("10秒等待完。");
}catch(InterruptedException e){
e.printStackTrace();
}
//thread5中会置flag=false终止thread1
t5.start();
try{
System.out.println("主程序等待10秒,确保thread5获得class的对象锁,确保thread1和被阻塞的线程都终止。");
Thread.sleep(10000);
System.out.println("10秒等待完。");
}catch(InterruptedException e){
e.printStackTrace();
} t0 = new Thread(new Thread0_052(rs)); //普通方法
t2 = new Thread(new Thread2_052(rs)); //另一个synchronized方法
t3 = new Thread(new Thread3_052(rs)); //synchronized static 方法
t4 = new Thread(new Thread4_052(rs)); //static方法 t0.start(); //调用了普通方法 //可以
t2.start(); //调用了另一个synchronized方法 //不行
t3.start(); //调用了synchronized static 方法 //不可以
t4.start(); //调用了static方法 //可以
}
} class Resource_052{
public boolean flag = true; public void method0(){
System.out.println("this is a ordinary method——method0.");
}
synchronized public void method1(){
while(flag){
System.out.println("this is a synchronized method——method1.");
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
synchronized public void method2(){
System.out.println("this is the second synchronized method——method2.");
}
synchronized public static void method3(){
System.out.println("this is a synchronized static method——method3.");
}
public static void method4(){
System.out.println("this is a ordinary static method——method4.");
} public void method5(){
synchronized(Resource_052.class){
while(true){
System.out.println("this is a synchronized static method——method5.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} synchronized public static void method6(){ //与method5等价
while(true){
System.out.println("this is a synchronized static method——method6.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} } class Thread1_052 implements Runnable{
private Resource_052 rs;
/**
* constructor
* @param rs
*/
public Thread1_052(Resource_052 rs){
this.rs = rs;
}
@Override
public void run(){
this.rs.method1(); //调用synchronized方法
}
}
class Thread0_052 implements Runnable{
private Resource_052 rs;
/**
* constructor
* @param rs
*/
public Thread0_052(Resource_052 rs){
this.rs = rs;
}
@Override
public void run(){
this.rs.method0(); //调用普通方法
}
}
class Thread2_052 implements Runnable{
private Resource_052 rs;
/**
* constructor
* @param rs
*/
public Thread2_052(Resource_052 rs){
this.rs = rs;
}
@Override
public void run(){
this.rs.method2(); //调用另一个synchronized方法
}
}
class Thread3_052 implements Runnable{
private Resource_052 rs;
/**
* constructor
* @param rs
*/
public Thread3_052(Resource_052 rs){
this.rs = rs;
}
@Override
public void run(){
this.rs.method3(); //调用synchronized static方法
}
}
class Thread4_052 implements Runnable{
private Resource_052 rs;
/**
* constructor
* @param rs
*/
public Thread4_052(Resource_052 rs){
this.rs = rs;
}
@Override
public void run(){
this.rs.method4(); //调用普通static方法
}
}
class Thread5_052 implements Runnable{
private Resource_052 rs;
/**
* constructor
* @param rs
*/
public Thread5_052(Resource_052 rs){
this.rs = rs;
}
@Override
public void run(){
rs.flag=false;
this.rs.method5(); //调用锁Class的方法
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
得到的结果如下:
==================================================================================================
调用synchronized方法的thread1启动后主程序等待2秒,确保在其它线程执行之前thread1获得对象锁
this is a synchronized method——method1.
this is a synchronized method——method1.
主程序等待10秒,等前面的线程除thread1和被阻塞的线程外都执行完成,后面的代码将做锁class测试....
this is a ordinary method——method0.
this is a synchronized static method——method3.
this is a ordinary static method——method4. //从这里的结果可以看到synchronized 普通方法method3没有执行
this is a synchronized method——method1.
this is a synchronized method——method1.
this is a synchronized method——method1.
this is a synchronized method——method1.
10秒等待完。
主程序等待10秒,确保thread5获得class的对象锁,确保thread1和被阻塞的线程都终止。
this is a synchronized static method——method5.
this is the second synchronized method——method2.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
10秒等待完。
this is a ordinary method——method0.
this is a ordinary static method——method4.
this is the second synchronized method——method2. //可以看到synchronized static方法method3没有执行
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
==================================================================================================
java线程之——synchronized的注意细节的更多相关文章
- java线程安全— synchronized和volatile
java线程安全— synchronized和volatile package threadsafe; public class TranditionalThreadSynchronized { pu ...
- java 线程及synchronized关键字
从本篇开始,我们将会逐渐总结关于java并发这一块的内容,也可以理解为是我的笔记,主要来自于一些博客和java书籍中的内容,所有的内容都是来自于他们之中并且加上了我自己的理解和认识. ...
- Java线程同步synchronized的理解
JVM中(留神:马上讲到的这两个存储区只在JVM内部与物理存储区无关)存在一个主内存(Main Memory),Java中所有的变量存储在主内存中,所有实例和实例的字段都在此区域,对于所有的线程是共享 ...
- 对象、对象监视器、同步队列、执行线程关系(synchronized的实现细节或原理)
synchronized在使用的时候底层细节你了解吗,相信很多同学对细节很少关注:比如竞争失败了的线程怎么安置,每个对象的监视器,线程执行synchronized时,其实是获取对象的监视器才能进入同步 ...
- java 线程安全 synchronized
一.线程安全问题: 并发编程的原则:设计并发编程的目的是为了使程序获得更高的执行效率,但绝不能出现数据一致性(数据准确)问题,如果并发程序连最基本的执行结果准确性都无法保证,那并发编程就没有任何意义. ...
- 关于java线程锁synchronized修饰普通方法与静态方法的区别
最近研究线程方面问题,关于这个synchronized锁修饰的问题,先是修饰普通方法,然后通过两个线程,各自执行自己对象的锁,发现方法执行互不影响,代码如下: private static int n ...
- java线程总结--synchronized关键字,原理以及相关的锁
在多线程编程中,synchronized关键字非常常见,当我们需要进行“同步”操作时,我们很多时候需要该该关键字对代码块或者方法进行锁定.被synchronized锁定的代码块,只能同时有一条线程访问 ...
- Java 线程 — synchronized、volatile、锁
线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只 ...
- Java线程(二):线程同步synchronized和volatile
上篇通过一个简单的例子说明了线程安全与不安全,在例子中不安全的情况下输出的结果恰好是逐个递增的(其实是巧合,多运行几次,会产生不同的输出结果),为什么会产生这样的结果呢,因为建立的Count对象是线程 ...
随机推荐
- DELPHI XE5开发WEB服务器及安卓手机客户端
Xe5开发web服务端和手机客户端 ------------------------------------- Delphi xe5作为最新开发利器,就类似如当年的DELPHI,功能强大,快发速度快, ...
- MongoDB 3.0 用户创建
摘要: MongoDB 3.0 安全权限访问控制,在添加用户上面3.0版本和之前的版本有很大的区别,这里就说明下3.0的添加用户的方法. 环境.测试: 在安装MongoDB之后,先关闭auth认证,进 ...
- codeforces 499B.Lecture 解题报告
题目链接:http://codeforces.com/problemset/problem/499/B 题目意思:给出两种语言下 m 个单词表(word1, word2)的一一对应,以及 profes ...
- Silverlight 动画性能
通过几个配置可以提高动画性能: Desired Frame Rate 在WEB项目中配置: <div id="silverlightControlHost"> < ...
- 【leetcode】Repeated DNA Sequences(middle)★
All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...
- 【leetcode】Reverse Bits(middle)
Reverse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represented in ...
- 【编程题目】输出 1 到最大的 N 位数
65.输出 1 到最大的 N 位数(运算)题目:输入数字 n,按顺序输出从 1 最大的 n 位 10 进制数.比如输入 3,则输出 1.2.3 一直到最大的 3 位数即 999. 思路:肯定要考虑数字 ...
- oc获得相册照片
- (void)addImage { if (CGRectGetMaxX(addImageView.frame)>SCREEN_WIDTH-CGRectGetWidth(addImageView ...
- 让U盘永不中毒的解决办法
一.背景: 在学校上课的时候,有个老师很潇洒的拿着一个U盘就来教室上课了.然后快上课的时候在电脑上准备播放课件.注意,这一瞬间其妙的事情发生了,课件因为他的U盘中病毒了,打不开了,老师当时笑了.后来又 ...
- October 9th 2016 Week 41st Sunday
No matter how resourceful you are, you can't fight fate. 人纵有万般能耐,终也敌不过天命. I find that I gradually be ...