synchronized 是 java 多线程编程中用于使线程之间的操作串行化的关键字。这种措施类似于数据库中使用排他锁实现并发控制,但是有所不同的是,数据库中是对数据对象加锁,而 java 则是对将要执行的代码加锁。

在 java 中使用 synchronized 关键字时需要注意以下几点:

1.synchronized 是针对同一个资源的访问作出限制。这是出现该关键字的原因。

2.对于类而言,某一个线程执行到一个 synchronized 修饰的类方法或者类方法中的代码段时,该方法或者代码段就被加上互斥锁,同时该类中的所有使用 synchronized 修饰的类方法或者类方法中的代码段都被加上互斥锁,但不影响没有使用 synchronized 修饰的类方法或者类方法中的代码段,同时也不影响该线程执行这些剩余已经被加上锁的类方法或者类方法中的代码段以及其他类中的任意方法;当线程执行完被 synchronized 修饰的类方法或者类方法中的代码段后,这些互斥锁都将同时被释放。

3.对于对象而言,某一个线程执行到一个 synchronized 修饰的对象方法或者对象方法中的代码段时,情况和 2 中一样。

4. 第 3 点和第 2 点相互之间没有影响

5.synchronized() 括号内所使用的内容指示将要封锁的资源是一个类还是一个对象中的方法或者代码块。由于无法对类声明中使用 synchronized 修饰符,所以对于类而言,需要使用类似于 synchronized(ClassName.class){/*...*/} 形式或者使用 synchronized 修饰类方法

实例代码如下:

(1)Printer 类

 public class Printer {
public static void printA()
{
System.out.println(Thread.currentThread() + ": invoke printA method");
synchronized(Printer.class)
{
for(int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread() + ": into printA method's loop...");
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
} public synchronized void printB()
{
System.out.println(Thread.currentThread() + ": invoke printB method");
for(int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread() + ": into printB method's loop...");
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}

(2)ThreadA 类

 package demo;

 public class ThreadA extends Thread{
Printer p = null;
public ThreadA(Printer p)
{
super("ThreadA");
this.p = p;
}
public void run()
{
//p.printA();
Printer.printA();
}
}

(3)ThreadB 类

 package demo;

 public class ThreadB extends Thread{
Printer p = null;
public ThreadB(Printer p)
{
super("ThreadB");
this.p = p;
}
public void run()
{
//p.printB();
Printer.printB();
}
}

(4)MainThread 类

 package demo;

 public class MainThread {
public static void main(String[] args)
{
Printer p = new Printer();
ThreadA ta = new ThreadA(p);
ThreadB tb = new ThreadB(p); ta.start();
try {
ta.join(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
tb.start();
}
}

运行结果如下:

Thread[ThreadA,5,main]: invoke printA method
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadB,5,main]: invoke printB method
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadB,5,main]: into printB method's loop...

从上述结果可以看出,ThreadA 首先调用 run 方法,并且进入了 printA 方法的 for 循环块,因此先获得了互斥锁;根据 2 即可得知 ThreadB 无法执行 printB 方法。在 MainThread 中加上 join(10) 为了给 ThreadA 更多的时间以便于让它能先进入 printA 方法(这是因为 ThreadA 需要在执行完一条 pirnt 语句之后才能获得互斥锁)。如果去掉 join 语句即可验证该点。

在上述的 Printer 类添加一个 printC 方法:

     public void printC()
{
System.out.println(Thread.currentThread() + ": invoke printC method");
}

创建一个 ThreadC 类:

 package demo;

 public class ThreadC extends Thread{
Printer p = null;
public ThreadC(Printer p)
{
this.p = p;
}
public void run()
{
for(int i = 0; i < 5; i++)
{
p.printC();
}
}
}

然后在 MainThread 中去掉 join 语句,激活线程 ThreadC,运行结果如下(各位测试时结果可能有所不同):

Thread[Thread-0,5,main]: invoke printC method
Thread[ThreadA,5,main]: invoke printA method
Thread[Thread-0,5,main]: invoke printC method
Thread[Thread-0,5,main]: invoke printC method
Thread[ThreadB,5,main]: invoke printB method
Thread[ThreadB,5,main]: into printB method's loop...
Thread[Thread-0,5,main]: invoke printC method
Thread[Thread-0,5,main]: invoke printC method
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadA,5,main]: into printA method's loop...

对于上述结果,大家可以结合 2 自己进行解释,对于 2 中剩余的观点以及对于对象的情况,也可以自行测试验证。下面验证 4 。

将 Printer 方法中的 printB 方法声明中的 static 关键字去掉,在 ThreadB 类 run 方法中使用 p.printB() 替换 Printer.printB() ,运行结果如下:

Thread[ThreadA,5,main]: invoke printA method
Thread[ThreadB,5,main]: invoke printB method
Thread[ThreadB,5,main]: into printB method's loop...
Thread[Thread-0,5,main]: invoke printC method
Thread[ThreadA,5,main]: into printA method's loop...
Thread[Thread-0,5,main]: invoke printC method
Thread[Thread-0,5,main]: invoke printC method
Thread[Thread-0,5,main]: invoke printC method
Thread[Thread-0,5,main]: invoke printC method
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadA,5,main]: into printA method's loop...
Thread[ThreadB,5,main]: into printB method's loop...
Thread[ThreadA,5,main]: into printA method's loop...

对于输出结果,各位看官可以细心分析分析

(未完待续。。。;-))

本文有参考:Devin Zhang 的博客

java synchronized关键字浅探的更多相关文章

  1. Java Synchronized 关键字

    本文内容 Synchronized 关键字 示例 Synchronized 方法 内部锁(Intrinsic Locks)和 Synchronization 参考资料 下载 Demo Synchron ...

  2. Java synchronized 关键字详解

    Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...

  3. Java synchronized关键字用法(清晰易懂)

    本篇随笔主要介绍 java 中 synchronized 关键字常用法,主要有以下四个方面: 1.实例方法同步 2.静态方法同步 3.实例方法中同步块 4.静态方法中同步块 我觉得在学习synchro ...

  4. java synchronized关键字

    引用其他人的一段话 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchro ...

  5. Java synchronized关键字的理解

    转载自:http://blog.csdn.net/xiao__gui/article/details/8188833 在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环 ...

  6. java synchronized关键字浅析

    synchronized这个关键字想必学Java的人都应该知道. 直接上例子: 方法级别实例 public class AtomicInteger { private int index; publi ...

  7. [java] java synchronized 关键字详解

    Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一 ...

  8. Java:synchronized关键字引出的多种锁

    前言 Java 中的 synchronized关键字可以在多线程环境下用来作为线程安全的同步锁.本文不讨论 synchronized 的具体使用,而是研究下synchronized底层的锁机制,以及这 ...

  9. java synchronized关键字的底层实现

    每个对象都有一个锁(Monitor,监视器锁),class对象也有锁,如果synchronized关键字修饰同步代码块,通过反编译可以看到,其实是有个monitorenter和monitorexit指 ...

随机推荐

  1. typedef函数指针使用方法

    1.简单的函数指针的应用 形式1:返回类型(*函数名)(參数表) char (*pFun)(int); char glFun(int a){ return;} void main() { pFun = ...

  2. purge

    RR级别 mysql V5.6 debug ; 测试1 会话1: mysql)); Query OK, rows affected (0.04 sec) mysql,"a"); Q ...

  3. 深入理解 CSS 中的行高与基线

    1.基本概念 1.  基线.底线.顶线.中线 注意:基线(base line)并不是汉字文字的下端沿,而是英文字母“x”的下端沿. 2. 内容区 内容区是指底线和顶线包裹的区域(行内元素display ...

  4. LinkedHashMap介绍

    转载:http://uule.iteye.com/blog/1522291 jdk1.7API文档链接:http://tool.oschina.net/apidocs/apidoc?api=jdk_7 ...

  5. 一款基于css3的3D图片翻页切换特效

    今天给大家分享一款基于css3的3D图片翻页切换特效.单击图片下方的滑块会切换上方的图片.动起你的鼠标试试吧,效果图如下: 在线预览   源码下载 实现的代码. html代码: <div id= ...

  6. 制作嵌入式linux文件系统(ramdisk,cramfs,squashfs)

    转:http://blog.csdn.net/zyb19831212/article/details/1887930 一.什么是文件系统 (Filesystem): A directory struc ...

  7. 小白日记46:kali渗透测试之Web渗透-SqlMap自动注入(四)-sqlmap参数详解- Enumeration,Brute force,UDF injection,File system,OS,Windows Registry,General,Miscellaneous

    sqlmap自动注入 Enumeration[数据枚举] --privileges -U username[CU 当前账号] -D dvwa -T users -C user --columns  [ ...

  8. myecplise 打开报错 Errors occurred during the build. Errors running builder 'DeploymentBuilder' on project 'myf'. Java.lang.NullPointerException

    Errors occurred during the build. Errors running builder 'DeploymentBuilder' on project 'myf'.Java.l ...

  9. Android 高级UI设计笔记15:HorizontalScrollView之 实现画廊式图片浏览器

    1. HorizontalScrollView 本来,画廊式的图片浏览器,使用Android中的Gallery就能轻松完成,但是Google说Gallery每次切换图片时都要新建视图,造成太多的资源浪 ...

  10. .net对各表的操作详细到字段的更改记录的日志

    存入数据库中,目前的字段包括操作人,操作时间,sql语句,被修改的字段,字段原值,操作人的身份. /// <summary> /// 添加操作日志 /// </summary> ...