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. iOS开发——UI篇Swift篇&UIToolbar

    UIToolbar class UIToolBarUISearchBar: UIViewController,UISearchBarDelegate { var titleString:String! ...

  2. MySql之char与varchar

    MySql之char与varchar的差别 char是一种固定长度的类型,varchar则是一种可变长度的类型.它们的差别是:  1. char(M)类型的数据列里.每一个值都占用M个字节.假设某个长 ...

  3. 内存管理和@property的属性

    内存管理和@property的属性 目录 对内存管理的理解 Objective C内存管理方式 内存的管理 对象的所有权和内存管理原则 合理解决内存管理带来的问题 自动释放池 @property的属性 ...

  4. MySQL--索引条件下推优化

    http://blog.163.com/li_hx/blog/static/1839914132015782821512/ 一 什么是“索引条件下推” “索引条件下推”,称为 Index Condit ...

  5. org.apache.hadoop.conf-Configuration

    终于遇到第一块硬骨头 Hadoop没有使用java.util.Properties管理配置文件,而是自己定义了一套配置文件管理系统和自己的API. package org.apache.hadoop. ...

  6. 短小实用 渗透用的Python小脚本

    渗透的很多时候,找到的工具并不适用,自己码代码才是王道,下面三个程序都是渗透时在网络上找不到合适工具,自己辛苦开发的,短小实用. 一.记录root密码小工具 root.py #!/usr/bin/py ...

  7. jquery相关代码

    1.jquery获取当前选中select的text值 var checkText=$("#slc1").find("option:selected").text ...

  8. HF Code Designer 代码生成器

    最近忙于项目和平台开发好久没写博客了,今天把最近的一个项目总结和大家分项一下. 在平台开发的过程中,代码生成器是必不可少的,Net领域的代码生成器比较多,以前用动软的,最早的那个版本还是开源,自己写了 ...

  9. Java学习笔记——多态性Polymorphism

    Java中实现多态的机制 Java中实现多态的机制靠的是父类或者接口定义的引用变量可以指向子类或者具体的实现类的实例对象,而程序调的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就 ...

  10. 双系统Linux(ubuntu)进入windows的NTFS分区之挂载错误

    自从装了双系统(ubuntu&win10)后,发现有时在ubuntu下无法进行win磁盘,于是在网上搜了点资料得以解决,并在此记录一下: 问题如下: 解决步骤: 1.ctrl+alt+t打开终 ...