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对象是线程 ...
随机推荐
- iOS 真机文件系统区分大小写,而模拟器可能不区分
模拟器区不区分大小写要看mac os是不是区分大小写,而这个和你的文件系统有关,如下图 如果你使用了默认的格式,就区分不了大小写了! 看来以后还是应该使用第二种格式啊!
- Windows下查看局域网内某台计算机的MAC地址
我们知道在局域网中,在Windows下,查看局域网内其他主机的ip和对应mac地址的命令是: arp -a 这样可以看到ip和mac地址的对应关系,还是比较方便的 但是有些时候使用arp命令并不能列出 ...
- ACM/ICPC 之 DFS求解欧拉通路路径(POJ2337)
判断是欧拉通路后,DFS简单剪枝求解字典序最小的欧拉通路路径 //Time:16Ms Memory:228K #include<iostream> #include<cstring& ...
- 在java项目中使用AES256 CBC加密
首先要注意一点,默认的JDK是不支持256位加密的,需要到Oracle官网下载加密增强文件(Java Cryptography Extension (JCE) Unlimited Strength J ...
- pydev导入eclipse
编辑器:Python 自带的 IDLE 简单快捷, 学习Python或者编写小型软件的时候.非常有用. 编辑器: Eclipse + pydev插件 1. Eclipse是写JAVA的IDE, 这样就 ...
- codeforces 425B Sereja and Table (枚举、位图)
输入n*m的01矩阵.以及k. n,m<=100,k<=10 问修改至多k个,使得矩阵内的各连通块(连着的0或1构成连通块)都是矩形,且不含另外的数字(边界为0(1)的矩形内不含1(0)) ...
- hiho一下第一周 最长回文子串
题目链接:http://hihocoder.com/contest/hiho1/problem/1 #include <iostream> #include <cstdio> ...
- ibatis中使用like模糊查询
select * from table1 where name like '%#name#%' 两种有效的方法: 1) 使用$代替#.此种方法就是去掉了类型检查,使用字符串连接,不过可能会有sql注入 ...
- VS VA助手补丁覆盖目录
以VS2010为例. VA_X.dll 复制到以下文件夹内,覆盖原文件. WinXP系统: %USERPROFILE%\Local Settings\Application Data\Microsof ...
- 使用autolayout,设置子控件的宽度 与父视图的宽度成比例大小(这样类似可以设置多个按钮平均横屏排列)
橙色是父视图,假设约束如上图. 绿色是子视图.重点宽度比例设置: 1. control-drag 选择 equal width2. 选中上面那个约束 注意 first item 和 second it ...