文档章节

java并发编程(1)——synchronized关键字解析

十二缸帕萨特
 十二缸帕萨特
发布于 2014/04/12 12:48
字数 1320
阅读 60
收藏 0

synchronized是Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

     一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

     二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

     四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

     五、以上规则对其它对象锁同样适用.


1、synchronized关键字的作用域有二种: 
1)是某个对象实例内synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法; 
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

3、synchronized关键字是不能继承的也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;


synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为

synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可

以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供

了更好的解决办法,那就是 synchronized 块。  
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:  
synchronized(syncObject) {  
//允许访问控制的代码  
}  
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机

制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。  


下面将用代码来实践


/*
 *         
 ****************************************************************************
 * 源文件名:  cn.com.thread.SynchronizedTest.java 													       
 * 功能: smart框架													   
 * 版本:	@version 1.0	                                                                   
 * 编制日期: 2014-4-12 下午12:49:25 						    						                                        
 * 修改历史: (主要历史变动原因及说明)		
 * YYYY-MM-DD |    Author      |	 Change Description		      
 * 2014-4-12    |    gaowenming     |     Created 
 */
package cn.com.thread;

/**
 * Description: <类功能描述>. <br>
 * <p>
 * <使用说明>
 * </p>
 * Makedate:2014-4-12 下午12:49:25
 * 
 * @author gaowenming
 * @version V1.0
 */
public class SynchronizedTest {

	/**
	 * 描述 : <描述函数实现的功能>. <br>
	 * <p>
	 * <使用方法说明>
	 * </p>
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		final PrintNumber pn = new PrintNumber();

		// 第一个线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				pn.print100();
			}
		}).start();

		// 第二个线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				pn.print10();
			}
		}).start();

	}

}

/**
 * 
 * 
 * @Description: 定义一个类,里面有2个方法
 * @author gaowenming
 * @date 2014-4-12 下午12:49:58
 * 
 */
class PrintNumber {
	/**
	 * 
	 * 描述 : <从1打印到10>. <br>
	 * <p>
	 * <使用方法说明>
	 * </p>
	 */
	public  void print10() {
		for (int i = 1; i <= 10; i++) {
			System.out.println("print10====================  " + i);
		}
	}

	/**
	 * 
	 * 描述 : <从1打印到100>. <br>
	 * <p>
	 * <使用方法说明>
	 * </p>
	 */
	public  void print100() {
		for (int i = 1; i <= 100; i++) {
			System.out.println("print100====================  " + i);
		}
	}

}

在PrintNumber类中定义了2个方法,一个是从1打印到10,另一个是从1打印到100,现在要求2个方法在执行的过程中互不干扰,在没有加synchronized的情况下,执行结果

print100====================  1

print10====================  1

print100====================  2

print10====================  2

print100====================  3

print10====================  3

print100====================  4

print10====================  4

print100====================  5

print100====================  6

print100====================  7

print100====================  8

print100====================  9

print100====================  10

print10====================  5

print100====================  11

print10====================  6

print10====================  7

print10====================  8

print10====================  9

print10====================  10


很明显2个方法已经在同时执行了,那么加上synchronized后,

.

......

print100====================  90

print100====================  91

print100====================  92

print100====================  93

print100====================  94

print100====================  95

print100====================  96

print100====================  97

print100====================  98

print100====================  99

print100====================  100

print10====================  1

print10====================  2

print10====================  3

print10====================  4

print10====================  5

print10====================  6

print10====================  7

print10====================  8

print10====================  9

print10====================  10




© 著作权归作者所有

十二缸帕萨特
粉丝 19
博文 65
码字总数 29186
作品 0
海淀
高级程序员
私信 提问
再有人问你synchronized是什么,就把这篇文章发给他。

在《深入理解Java虚拟机》中,有这样一段话: synchronized关键字在需要原子性、可见性和有序性这三种特性的时候都可以作为其中一种解决方案,看起来是“万能”的。的确,大部分并发控制操作...

Java填坑之路
2018/08/07
0
0
求你了,再问你Java内存模型的时候别再给我讲堆栈方法区了…

GitHub 4.1k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 4.1k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 4.1k Star 的Java工程师成神之路 ,真的确定不来了解一下吗...

Hollis
07/02
0
0
基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存、CPU、缓存等予以说明。实际上,在实...

leoliu168
2018/11/08
0
0
Java 并发编程源码解析汇总篇

java并发编程,内存模型 java并发编程,volatile内存实现和原理 Java并发编程,并发基础 Java 并发编程,线程池(ThreadPoolExecutor)源码解析 Java并发编程,Executor 框架介绍 Java并发编...

郑加威
2018/12/23
0
0
再有人问你volatile是什么,就把这篇文章发给他

Java语言为了解决并发编程中存在的原子性、可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized、volatile、final、concurren包等。在前一篇文章中,我们也介绍了syn...

Java小铺
2018/08/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
9分钟前
1
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0
轻量级 HTTP(s) 代理 TinyProxy

CentOS 下安装 TinyProxy yum install -y tinyproxy 启动、停止、重启 # 启动service tinyproxy start# 停止service tinyproxy stop# 重启service tinyproxy restart 相关配置 默认...

Anoyi
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部