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对象是线程 ...
随机推荐
- POJ 1917
http://poj.org/problem?id=1917 poj的字符串的一道水题. 题意么无关紧要, 反正输出的第一行就是把那个<>去掉,s1<s2>s3<s4&g ...
- ios 音乐播放,音乐信息显示方法
下面的博客写的很清楚了 http://msching.github.io/blog/page/2/ 主要涉及AVAudioPlayer和下面这几个函数 MPNowPlayingInfoCenter.d ...
- QPS计算方法
2016年3月14日 13:55:39 星期一 好久没写文章了, 神烦.....
- STL:原地归并排序模板(InplaceMergeSort)
原理:就是在归并排序上改进,以时间复杂度换空间复杂度,利用元素反转完成排序 具体过程如下: 具体操作看代码吧,应该没什么难度,主要是reverse要反转三次 typedef int Position; ...
- poj 2389.Bull Math 解题报告
题目链接:http://poj.org/problem?id=2389 题目意思:就是大整数乘法. 题目中说每个整数不超过 40 位,是错的!!!要开大点,这里我开到100. 其实大整数乘法还是第一次 ...
- mybatis反向生成sql,基本的增删改查
用到的几个文件 MyBatisGeneratorProxy.java package com.timestech.wsgk.test.tools; import static org.mybatis. ...
- 【leetcode】 Unique Binary Search Trees II (middle)☆
Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...
- 【XLL API 函数】xlfUnregister (Form 2)
此函数可以被 Excel 已经载入的 XLL 或 DLL 调用.它等效于宏表函数 UNREGISTER. xlfUnregister 有两种调用形式: 形式1:Unregister 单独的命令或函数 ...
- 模拟操作网页 webBrowser
C# 获取IFrame中body元素 (winform) 方法1. 找出iframe的b.html的src , 利用webbrowser去加载b.html HtmlElementCollection ...
- android中点击空白处隐藏软键盘
InputMethodManager manager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERV ...