synchronized 基本用法
常见三种使用方式
1)普通同步方法,锁是当前实例;
2)静态同步方法,锁是当前类的Class实例,Class数据存在永久代中,是该类的一个全局锁;
3)对于同步代码块,锁是synchronized括号里配置的对象。
方式一 普通方法通过synchronized修饰
1)不采用synchronized 当创建两个线程对象 线程t1 t2中采用同一个实例化类对象 调用method方法 会交异步执行 互补影响
package cn.ac.bcc.sync;
/**
* 普通同步方法通过synchronized修饰
* @author Administrator
*
*/
public class PtMethod { /**
* 1)不采用synchronized修饰
* @param s
*/
public void method(String s){
if(s.equals("a")){
System.out.println(Thread.currentThread().getName()+": a"); try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName()+": b");
}
} public static void main(String[] args) {
//创建当前类对象实例
final PtMethod ptMethod = new PtMethod(); //创建线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
ptMethod.method("a");
}
}); Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
ptMethod.method("b");
} }); t1.start();
t2.start();
} }
运行结果:
Thread-1: b
Thread-0: a
2)采用synchronized 当创建两个线程对象 线程t1 t2 中采用同一个实例化对象 调用synchronized修饰的method方法 method方法中线程睡眠一秒钟 当线程t1优先抢占到method方法的执行权时由于method方法被synchronized修饰 method方法被实例化对象ptMethod对象锁锁住 当t2线程同样是ptMethod实例化对象调用当前method方法 由于两个线程t1 t2 都采用的是同一个实例化对象ptMethod 对象锁 只有t1运行完成后 t2中线程中的ptMethod对象才能调用method方法。由于method中获取当前调用线程睡眠 t2要等t1中调用的method睡眠唤醒之后执行完方法才能执行。
public class PtMethod {
/**
* 1)采用synchronized修饰
* @param s
*/
public synchronized void method(String s){
if(s.equals("a")){
System.out.println(Thread.currentThread().getName()+": a");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName()+": b");
}
}
public static void main(String[] args) {
//创建当前类对象实例
final PtMethod ptMethod = new PtMethod();
//创建线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
ptMethod.method("a");
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
ptMethod.method("b");
}
});
t1.start();
t2.start();
}
}
3)采用synchronized修饰 创建两个线程对象 创建当前类实例对象 ptMethod1 ptMethod2 t1线程运行ptMetod1 t2线程运行ptMethod2 对象分别调用mehod方法 运行结果如下 ,由于两个线程分别采用的是两个不同的实例对象 当两个实例对象调用method方法时 synchronized判断当前锁对象并不相同 所以里两个对象向都分别调用了method方法,而不需要等待
public class PtMethod {
/**
* 1)采用synchronized修饰
* @param s
*/
public synchronized void method(String s){
if(s.equals("a")){
System.out.println(Thread.currentThread().getName()+": a");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName()+": b");
}
}
public static void main(String[] args) {
//创建当前类对象实例
final PtMethod ptMethod1 = new PtMethod();
final PtMethod ptMethod2 = new PtMethod();
//创建线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
ptMethod1.method("a");
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
ptMethod2.method("b");
}
});
t1.start();
t2.start();
}
}
运行结果:
Thread-0: a
Thread-1: b
二、synchronized修饰静态方法
采用synchronized 修饰的静态方法 两个线程通过不同的 类实例对象调用 这个方法 如何加锁 这是可以将该方法修改为static 方法 并synchronized修饰
public class SyncDemo {
/**
* 类方法 synchronized修饰 解决多个线程调用当前类不同实例采用同步锁方法
* @param s
*/
public static synchronized void method(String s){
if(s.equals("a")){
System.out.println(Thread.currentThread().getName()+": a");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName()+": b");
}
}
public static void main(String[] args) {
final SyncDemo syncDemo1 = new SyncDemo();
final SyncDemo syncDemo2 = new SyncDemo();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
syncDemo1.method("a");
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
syncDemo2.method("b");
}});
t1.start();
t2.start();
}
}
三、同步代码块
1)当两个并发线程同时访问一个对象的同步代码块synchronized(this),在某一时刻只有一条线程才能访问该同步代码块
public class SyncDemo1 implements Runnable {
public static void main(String[] args) {
SyncDemo1 syncDemo1 = new SyncDemo1();
new Thread(syncDemo1,"a").start();;
new Thread(syncDemo1,"b").start();;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+"执行开始run方法");
synchronized (this) {
System.out.println(Thread.currentThread().getName());
}
}
}
运行结果: 当b抢到执行权只有b线程执行完成a线程才能继续执行
b执行开始run方法
b
a执行开始run方法
a
2)当一个线程访问object对象中的synchronized(this)同步代码块时,另一个线程可以访问object对象的非同步代码块
package cn.ac.bcc.sync;
public class SyncDemo2 {
public void method1(){
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"线程同步代码块");
}
}
public void method2(){
System.out.println(Thread.currentThread().getName()+"当两个线程访问同一个object 中的方法 一个线程访问线程同步方法 另一个可以方位object对象的非线程同步方法");
}
public static void main(String[] args) {
final SyncDemo2 syncDemo2 = new SyncDemo2();
//创建两个线程对象
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
syncDemo2.method1();
}
},"t1");
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
syncDemo2.method2();
}
},"t2");
t1.start();
t2.start();
}
}
3)当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
package cn.ac.bcc.sync;
public class SyncDemo2 {
public void method1(){
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"线程同步代码块");
try {
System.out.println(Thread.currentThread().getName()+"睡一会");
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void method2(){
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"访问线程同步代码块");
}
}
public static void main(String[] args) {
final SyncDemo2 syncDemo2 = new SyncDemo2();
//创建两个线程对象
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
syncDemo2.method1();
}
},"t1");
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
syncDemo2.method2();
}
},"t2");
t1.start();
t2.start();
}
}
运行结果:
t1线程同步代码块
t1睡一会
10秒后t2才能访问当前对象其他同步代码块修饰的方法
t1线程同步代码块
t1睡一会
t2访问线程同步代码块
synchronized 基本用法的更多相关文章
- Java中Synchronized的用法
原文:http://blog.csdn.net/luoweifu/article/details/46613015 作者:luoweifu 转载请标名出处 <编程思想之多线程与多进程(1)——以 ...
- Synchronized的用法
synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码 ...
- 巨人大哥谈Java中的Synchronized关键字用法
巨人大哥谈Java中的Synchronized关键字用法 认识synchronized 对于写多线程程序的人来说,经常碰到的就是并发问题,对于容易出现并发问题的地方价格synchronized基本上就 ...
- synchronized关键字用法
看到网上很多讲synchronized关键字用法的文章,说的都很有道理,也很深刻,但是看完总感觉脑袋里还是有点乱乱的.经过一番自己的思考后,想从自己的思考角度出发,来说一说synchronized关键 ...
- Java 中 synchronized的用法详解(四种用法)
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.本文给大家介绍java中 synchronized的用法,对本文感兴趣的朋友一起看看吧 ...
- 【转】Java中Synchronized的用法
<编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程>一文详细讲述了线程.进程的关系及在操作系统中的表现,这是多线程学习必须了解的基础.本文将接着讲一下Java线程同步中的一 ...
- iOS 线程安全之@synchronized的用法
@synchronized(self)的用法: @synchronized 的作用是创建一个互斥锁,保证此时没有其它线程对self对象进行修改.这个是objective-c的一个锁定令牌,防止self ...
- Java synchronized关键字用法(清晰易懂)
本篇随笔主要介绍 java 中 synchronized 关键字常用法,主要有以下四个方面: 1.实例方法同步 2.静态方法同步 3.实例方法中同步块 4.静态方法中同步块 我觉得在学习synchro ...
- java中synchronized的用法详解
记下来,很重要. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchron ...
- synchronized Lock用法
在介绍Lock与synchronized时,先介绍下Lock: public interface Lock { void lock(); void lockInterruptibly() throws ...
随机推荐
- 《C++面向对象程序设计》之变量的生存期
<C++面向对象程序设计>之变量的生存期 静态生存期 (1)全局静态生存期:在函数体外声明,作用域从声明处开始到文件结尾处结束,称其有文件作用域,相当于全局变量 . (2)局部静态生存期: ...
- Google pieCharts的学习
在公司项目开发过程中, 尤其是在网站的开发过程中,用到很多的前端的插件,在这里, 我简单介绍下近期Google pieCharts的是使用方法 https://developers.google.co ...
- spring的struts简单介绍
之前一段时间学习了springmvc+mybatis+spring框架,突然对之前的struts东西有点陌生, 所以这里简单记录下温故而知新的东西吧. 1. 首先建立一个Dynamic Web Pr ...
- 【extjs6学习笔记】0.4 准备: 书籍与文档
Ext JS 6 By Example Ext JS Essentials Learning Ext JS - Fourth Edition Ext JS 6: Getting Started htt ...
- 定时器new Timer().schedule()的使用
Timer是一种工具,线程用其安排以后在后台线程中执行的任务.可安排任务执行一次,或者定期重复执行.实际上是个线程,定时调度所拥有的TimerTasks. TimerTask是一个抽象类,它的子类由 ...
- IOS 拖拽事件(手势识别)
@interface NJViewController () @property (weak, nonatomic) IBOutlet UIView *customView; @end @implem ...
- 可以使用可用的服务和参数调用在“eWorld.WCFImplement.ServiceImplement.ImageArchiveService”类型上使用“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的构造函数: 无法解析参数'eWorld.WCFBLL.ImageArchive.IDocumentOperation
可以使用可用的服务和参数调用在“eWorld.WCFImplement.ServiceImplement.ImageArchiveService”类型上使用“Autofac.Core.Activato ...
- oc语言基础整理
objc.h---------------- typedef struct objc_class *Class; struct objc_object { Class isa OBJC_ISA_AV ...
- PHP数组排序方法总结
随着PHP的快速发展,用它的人越来越多,在PHP数组学习摘录部分了解到最基本的PHP数组的建立和数组元素的显示.需要深入学习下PHP数组的相关操作.首先接触的就是PHP数组排序.降序的排序问题. so ...
- Restful API 的设计规范
RESTful 是目前最流行的 API 设计规范,用于 Web 数据接口的设计.降低开发的复杂性,提高系统的可伸缩性. Restful API接口规范包括以下部分: 一.协议 API与用户的通信协议, ...