synchronized作用:
保证代码执行的原子性;
保证可见性(与volatile作用相同)

JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。
假如再细的分类,synchronized可作用于instance变量、object reference(对象引用,例如this)、static函数和class literals(类名称字面常量)身上。
下面讨论synchronized用到不同地方对代码产生的影响:

1.
对于非static的情况,synchronized是对象级别的,其实质是将synchronized作用于对象引用(object reference)上,即拿到p1对象锁的线程,对p1的fun()方法有同步互斥作用,不同的对象之间坚持“和平共处”。
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都能够调用他们。
(1)把synchronized当作函数修饰符时,示例代码如下:
public synchronized void method(){
//….
}
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?他锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,他们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却能够任意调用这个被加了synchronized关键字的方法。上边的示例代码等同于如下代码:
public void method()
{
synchronized (this) // (1)
{
//…..
}
}
(1)处的this指的是什么呢?他指的就是调用这个方法的对象,如P1。可见,同步方法实质是将synchronized作用于Object Reference。那个拿到了P1对象锁的线程,才能够调用P1的同步方法,而对P2而言,P1这个锁和他毫不相干,代码也可能在这种情形下摆脱同步机制的控制,造成数据混乱,譬如同时操作静态变量时。
(2).同步块,示例代码如下:
public void method(SomeObject so) {
synchronized(so)
{
//…..
}
}
这时,锁就是so这个对象,谁拿到这个锁谁就能够运行他所控制的那段代码。当有一个明确的对象作为锁时,就能够这样写代码,但当没有明确的对象作为锁,只是想让一段代码同步时,能够创建一个特别的instance变量(它得是个对象)来充当锁:
class Foo implements Runnable
{
private byte[] lock = new byte[0]; // 特别的instance变量
Public void method()
{
synchronized(lock) { //… }
}
//…..
}
注:零长度的byte数组对象创建起来将比任何对象都经济。查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
2.
如果方法用static修饰,synchronized的作用范围就是class一级的,它对类的所有对象起作用。
将synchronized作用于static 函数,,示例代码如下:
Class Foo
{
public static synchronized void method1() // 同步的static 函数
{
//….
}
public void method2()
{
synchronized(Foo.class) // class literal(类名称字面常量)
//请注意,Foo.class也是一个对象,类型是Class,在一个ClassLoader里,它是唯一的。
}
}
代码中的method2()方法是把class literal作为锁的情况,他和同步的static函数产生的效果是相同的,
取得的锁很特别,是当前调用这个方法的对象所属的类(Class类,而不再是由这个Class产生的某个具体对象了)。

http://www.strutshome.com/index.php/archives/495

http://www.2cto.com/kf/201206/134899.html

http://tech.it168.com/j/2008-01-30/200801302324557.shtml

1.
A: synchronized static是某个类的范围,synchronized static cSync{}防止多个线程同时访问这个 类中的synchronized static 方法。它可以对类的所有对象实例起作用。
B: synchronized 是某实例的范围,synchronized isSync(){}防止多个线程同时访问这个实例中的synchronized 方法。

2.
synchronized方法与synchronized代码快的区别
synchronized methods(){} 与synchronized(this){}之间没有什么区别,只是 synchronized methods(){} 便于阅读理解,
而synchronized(this){}可以更精确的控制冲突限制访问区域,有时候表现更高效率。

3.synchronized关键字是不能继承的,即,父类的synchronized方法在子类中不是synchronized,必须要重新的显式的声明为synchronized才行。

4.实现同步需要很大的系统开销,导致延迟等待,甚至可能造成死锁,所以在非多线程情况下不要使用。

http://www.cnblogs.com/shipengzhi/articles/2223100.html

代码示例:

synchronized使用在方法中是锁住当前对象,此对象中其它synchrinized方法都会阻塞。

synchronized(this)示例:

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /*2015-4-29*/
public class SynchronizedTest {
public static void main(String[] args) throws InterruptedException {
Task task=new Task(true);
Thread readThread=new Thread(task, "Reader");
readThread.start();
TimeUnit.SECONDS.sleep(2); task.setRead(false);
Thread writeThread=new Thread(task, "Writer");
writeThread.start();
}
} class Task implements Runnable{
private boolean isRead;
public Task(boolean isRead) {
this.isRead=isRead;
}
private Logger logger=LoggerFactory.getLogger(Task.class);
@Override
public void run() {
try {
if (isRead) {
read();
}else {
write();
} } catch (InterruptedException e) {
e.printStackTrace();
}
} public void read() throws InterruptedException{
synchronized (this) {
logger.info("Enter read() synchronized");
TimeUnit.SECONDS.sleep(20);
logger.info("Ready to leave read() synchronized");
}
} public void write(){
logger.info("enter write()");
synchronized (this) {
logger.info("enter write() synchronized");
logger.info("Ready to leave write() synchronied");
}
logger.info("Ready to leave write()");
} public void setRead(boolean isRead) {
this.isRead = isRead;
} }

输出:

[2015-04-30 06:30:21,290] [Reader] INFO - Enter read() synchronized
[2015-04-30 06:30:23,290] [Writer] INFO - enter write()
[2015-04-30 06:30:41,290] [Reader] INFO - Ready to leave read() synchronized
[2015-04-30 06:30:41,290] [Writer] INFO - enter write() synchronized
[2015-04-30 06:30:41,290] [Writer] INFO - Ready to leave write() synchronied
[2015-04-30 06:30:41,290] [Writer] INFO - Ready to leave write()

synchronized method_name示例:

package thread.synchronizedTest;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class SynchronizedMethodTest {
public static void main(String[] args) throws InterruptedException {
Task3 task3 = new Task3(true);
Thread readThread = new Thread(task3, "Reader");
readThread.start();
TimeUnit.SECONDS.sleep(2); task3.setRead(false);
Thread writeThread = new Thread(task3, "Writer");
writeThread.start();
}
} class Task3 implements Runnable {
private boolean isRead; public Task3(boolean isRead) {
this.isRead = isRead;
} private Logger logger = LoggerFactory.getLogger(Task3.class); @Override
public void run() {
try {
if (isRead) {
read();
} else {
write();
} } catch (InterruptedException e) {
e.printStackTrace();
}
} public synchronized void read() throws InterruptedException {
logger.info("Enter read() synchronized");
TimeUnit.SECONDS.sleep(20);
logger.info("Ready to leave read() synchronized");
} public synchronized void write() {
logger.info("enter write()");
// synchronized (this) {
logger.info("enter write() synchronized");
logger.info("Ready to leave write() synchronied");
// }
logger.info("Ready to leave write()");
} public void setRead(boolean isRead) {
this.isRead = isRead;
} }

输出:

[2015-04-30 07:02:04,583] [Reader] INFO - Enter read() synchronized
[2015-04-30 07:02:24,583] [Reader] INFO - Ready to leave read() synchronized
[2015-04-30 07:02:24,583] [Writer] INFO - enter write()
[2015-04-30 07:02:24,583] [Writer] INFO - enter write() synchronized
[2015-04-30 07:02:24,583] [Writer] INFO - Ready to leave write() synchronied
[2015-04-30 07:02:24,583] [Writer] INFO - Ready to leave write()

使用一个声明的变量作为锁时,可以让锁的粒度更小,如果合理使用会提高程序执行效率:

package thread.synchronizedTest;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /*2015-4-29*/
public class SynchronizedLockObjectTest {
public static void main(String[] args) throws InterruptedException {
Task2 task2=new Task2(true);
Thread readThread=new Thread(task2, "Reader");
readThread.start();
TimeUnit.SECONDS.sleep(2); task2.setRead(false);
Thread writeThread=new Thread(task2, "Writer");
writeThread.start();
}
} class Task2 implements Runnable{ private byte[] readLock = new byte[0]; // 特别的instance变量
private byte[] writeLock = new byte[0]; // 特别的instance变量 private boolean isRead;
public Task2(boolean isRead) {
this.isRead=isRead;
}
private Logger logger=LoggerFactory.getLogger(Task2.class);
@Override
public void run() {
try {
if (isRead) {
read();
}else {
write();
} } catch (InterruptedException e) {
e.printStackTrace();
}
} public void read() throws InterruptedException{
synchronized (readLock) {
logger.info("Enter read() synchronized");
TimeUnit.SECONDS.sleep(20);
logger.info("Ready to leave read() synchronized");
}
} public void write(){
logger.info("enter write()");
synchronized (writeLock) {
logger.info("enter write() synchronized");
logger.info("Ready to leave write() synchronied");
}
logger.info("Ready to leave write()");
} public void setRead(boolean isRead) {
this.isRead = isRead;
} }

输出:

[2015-04-30 06:37:20,148] [Reader] INFO - Enter read() synchronized
[2015-04-30 06:37:22,148] [Writer] INFO - enter write()
[2015-04-30 06:37:22,148] [Writer] INFO - enter write() synchronized
[2015-04-30 06:37:22,148] [Writer] INFO - Ready to leave write() synchronied
[2015-04-30 06:37:22,148] [Writer] INFO - Ready to leave write()
[2015-04-30 06:37:40,149] [Reader] INFO - Ready to leave read() synchronized

synchronized(字段)和synchronized(当前对象)在一个实例中同时存在时,两个方法会同时执行,因为synchronized持有的对象不同,一个是当前对象,一个字段对象:

package thread.synchronizedTest;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class SychronizedLockFieldorMethod {
public static void main(String[] args) throws InterruptedException {
Task4 task4 = new Task4(true);
Thread readThread = new Thread(task4, "Reader");
readThread.start();
TimeUnit.SECONDS.sleep(2); task4.setRead(false);
Thread writeThread = new Thread(task4, "Writer");
writeThread.start();
}
} class Task4 implements Runnable { private byte[] readLock = new byte[0]; // 特别的instance变量
private byte[] writeLock = new byte[0]; // 特别的instance变量 private boolean isRead; public Task4(boolean isRead) {
this.isRead = isRead;
} private Logger logger = LoggerFactory.getLogger(Task4.class); @Override
public void run() {
try {
if (isRead) {
read();
} else {
write();
} } catch (InterruptedException e) {
e.printStackTrace();
}
} public synchronized void read() throws InterruptedException {
// synchronized (readLock) {
logger.info("Enter read() synchronized");
TimeUnit.SECONDS.sleep(20);
logger.info("Ready to leave read() synchronized");
// }
} public void write() {
logger.info("enter write()");
synchronized (writeLock) {
logger.info("enter write() synchronized");
logger.info("Ready to leave write() synchronied");
}
logger.info("Ready to leave write()");
} public void setRead(boolean isRead) {
this.isRead = isRead;
} }

输出:

[2015-04-30 06:54:41,294] [Reader] INFO - Enter read() synchronized
[2015-04-30 06:54:43,294] [Writer] INFO - enter write()
[2015-04-30 06:54:43,294] [Writer] INFO - enter write() synchronized
[2015-04-30 06:54:43,294] [Writer] INFO - Ready to leave write() synchronied
[2015-04-30 06:54:43,294] [Writer] INFO - Ready to leave write()
[2015-04-30 06:55:01,295] [Reader] INFO - Ready to leave read() synchronized

synchronized如果是一个入参,则不能起到同步的作用。因为这种场景和synchronized(this)的原理是一样的。但每次入参都是不同的对象,这些不同的对象不能形成互斥

import java.util.concurrent.TimeUnit;

public class SynchronizedParameter implements Runnable {
private static Biz biz = new Biz(); private String key; public SynchronizedParameter(String key) {
this.key = key;
} public static void main(String[] args) throws InterruptedException { String key1 = "key1";
Thread thread1 = new Thread(new SynchronizedParameter(key1), key1);
String key2 = "key2";
Thread thread2 = new Thread(new SynchronizedParameter(key2), key2);
Thread thread2_bak = new Thread(new SynchronizedParameter(key2), key2 + "bak"); thread1.start();
thread2.start();
thread2_bak.start(); thread1.join();
thread2.join();
thread2_bak.join(); System.out.println(Thread.currentThread() + "end...");
} @Override
public void run() {
biz.handle(key);
} public void setKey(String key) {
this.key = key;
} } class Biz { public void handle(String key) {
System.out.println(Thread.currentThread() + " " + key + " " + System.currentTimeMillis());
synchronized (key) {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread() + " " + key + " " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
Thread[key1,5,main] key1 1476842469690
Thread[key2,5,main] key2 1476842469691
Thread[key2bak,5,main] key2 1476842469695
Thread[key2,5,main] key2 1476842470691
Thread[key1,5,main] key1 1476842470691
Thread[key2bak,5,main] key2 1476842471691
Thread[main,5,main]end...

synchronized常见用法解析及示例的更多相关文章

  1. [转]Linux中find常见用法示例

    Linux中find常见用法示例[转]·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;find命令的参 ...

  2. Linux下命令行cURL的10种常见用法示例

    curl的命令行工具功能非常强大,这些数据交互的功能基本上都是通过URL方式进行的,下面这篇文章主要给大家分享了在Linux中命令行cURL的10种常见用法示例,通过示例代码介绍的非常详细,需要的朋友 ...

  3. Linux中 find 常见用法示例

    Linux中find常见用法示例 #find path -option [ -print ] [ -exec -ok command ] {} \; #-print 将查找到的文件输出到标准输出 #- ...

  4. STL priority_queue 常见用法详解

    <算法笔记>学习笔记 priority_queue 常见用法详解 //priority_queue又称优先队列,其底层时用堆来实现的. //在优先队列中,队首元素一定是当前队列中优先级最高 ...

  5. Linux中find常见用法

    Linux中find常见用法示例 ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数 ...

  6. php中的curl使用入门教程和常见用法实例

    摘要: [目录] php中的curl使用入门教程和常见用法实例 一.curl的优势 二.curl的简单使用步骤 三.错误处理 四.获取curl请求的具体信息 五.使用curl发送post请求 六.文件 ...

  7. find常见用法

    Linux中find常见用法示例 ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数 ...

  8. iOS 开发多线程篇—GCD的常见用法

    iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...

  9. iOS开发多线程篇—GCD的常见用法

    iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...

随机推荐

  1. [Powershell] FTP Download File

    # Config $today = Get-Date -UFormat "%Y%m%d" $LogFilePath = "d:\ftpLog_$today.txt&quo ...

  2. PowerShell_零基础自学课程_5_自定义PowerShell环境及Powershell中的基本概念

    PowerShell_零基础自学课程_5_自定义PowerShell环境及Powershell中的基本概念 据我个人所知,windows下的cmd shell除了能够通过修改系统参数来对其中的环境变量 ...

  3. smarty模板执行原理

    为了实现程序的业务逻辑和内容表现页面的分离从而提高开发速度,php 引入了模板引擎的概念,php 模板引擎里面最流行的可以说是smarty了,smarty因其功能强大而且速度快而被广大php web开 ...

  4. MLC固态硬盘,与入量是3000次P/E

    固态硬盘是什么,固态硬盘寿命有多长 SSD泛指使用闪存芯片组成的SSD固态硬盘,是使用FLASH闪存颗粒作为存储单元,不再使用传统的机械存储方法,使用模拟的方式虚拟出传统 硬盘存取方式和扇区等,也可以 ...

  5. JSTL核心标签库学习笔记

    写的很简单,不一定会有用,如果想要详细的话,建议看API啊--- 不过在这里推荐一个地址,http://www.yiibai.com/jstl/  希望对你们有帮助啊,很好的教材啊 1.<c:i ...

  6. hdu 3853 LOOPS(概率 dp 期望)

    Problem Description Akemi Homura is a Mahou Shoujo (Puella Magi/Magical Girl). Homura wants to help ...

  7. SpringMVC的@ResponseBody返回JSON,中文乱码问题的解决.

    SpringMVC的@ResponseBody,返回json,如果有中文显示乱码的解决办法. 在SpringMVC的配置文件中 <bean class="org.springframe ...

  8. 关于MemoryBarrier

    备注:OSG  OpenThread::Atomic.cpp中MemoryBarrier(); Atomic::operator unsigned() const { #if defined(_OPE ...

  9. iOS新的旅程之Swift语言的学习

    好久都没有来这个熟悉而又陌生的地方啦, 想想已经有两三个月了吧,不过我相信以后还是会经常来的啦,因为忙碌的学习已经过去啦,剩下的就是要好好的总结好好的复习了,好好的熟悉下我们之前学习的知识点,将他们有 ...

  10. JQuery hover(over,out) 使用笔记

    转载自:http://www.douban.com/note/202404884/ JQuery hover(over,out) 使用笔记 JavaScript 下.onmouseover() 和 o ...