继承Runnable 实现Synchronized 同步锁
- 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法。
- 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识。
- java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
- java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,知道线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。
- java的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的
若一个非抽象类实现一个接口,就必须重写接口中所有的方法,所以你实现Runnable接口时,会重写run()方法,run()方法只是把该线程编程可就绪状态,start()方法是将该线程变为可运行状态,好好理解下。。。
误区一:synchronized关键字只能用在实现Runnable或者继承了Thread类的子类的方法里面。
正解:如果有一块代码(或方法)可能被多个线程同时访问,然后里面操作的数据修改操作可能因为不同线程的操作而不一致的时候,使用synchronized锁定这块代码,确保同时只有一个线程访问这个代码块。也就是说,关键字synchronized可以用在任何类的方法里面,即使该类没有实现Runnable接口或者继承Thread类。
误区二:synchronized(this)和synchronized(object)作用范围完全不同。
正解:当多个线程访问同一个类 A 的方法 A() 的时候。并且,这个方法 A() ,要求一个线程执行完了之后再给另外一个线程去执行。那么,这个方法 A() 就必须加上 synchronized 关键字,或者,在该方法 A() 中写上
synchronized(this//指代当前类A的实例) { }
如果不在声明方法 A() 时,加上 synchronized 关键字,或者,不在方法 A() 中加上 synchronized(this){ }
同步块的时候可以在线程类的 run() 方法内
synchronized(Object //指代类A的实例){
Object.A();
}
实现多线程同时有序访问该同步块内类 A 的方法 A() 的目的。
object本身就包含this的情况。
this 指代的是当前同步块所在方法所在的类,当不需要引用别的类的时候。
object 指代的是需要调用的类,引用了别的类,且需要处理多线程并发访问时,object 指代的是被引用的类。如果没有引用别的类,则指代的就是同步块所在方法所在的类本身
一般来说,一个方法处理的内容很多,如果synchronized修饰以后,其他同步方法就必须等待其执行完毕才可以继续执行,如果该方法需要较长时间处理,这就明显会降低效率,失去了多线程的意义,所以我们可以考虑将同步的范围缩小,即从同步一个方法缩小为同步一段代码块,这就是同步代码块产生的原因。同步代码块的语法是:
- synchronized (this) {}
- synchronized (object) {}
synchronized(this)我称之为this同步代码块,针对的是当前对象;synchronized(object)我称之为非this同步代码块,针对的是object对象。
记住一点即可:不论是同步方法还是同步代码块,实质上都是争夺锁的问题,而锁一定是对象级的,即一个对象只会产生一个锁,所以只要有一个线程在执行synchronized修饰的东西(不论是方法还是代码块),那么其他线程都无法访问被synchronized修饰的方法或代码块。
但是注意使用非this同步代码块的时候,里面的object不要用String类型的,因为大家都知道JVM具有String常量池缓存的功能,所以使用String类型可能产生问题。
下面用一个栗子来区分同步方法还有同步代码块的synchronized (this)和synchronized (object)
- MethodSync 方法
例如 :
- public class MethodSync{
- private String anyString;
- public MultiSyn(String anyString) {
- this.anyString = anyString;
- }
/*
* 同步类方法
* @Task : 测试 synchronized 修饰方法时锁定的是调用该方法的对象
* @param name 线程的标记名称
*/
public synchronized void method(String name){
System.out.println(name + " Start a sync method");
try{
Thread.sleep(300);
}catch(InterruptedException e){}
System.out.println(name + " End the sync method");
}- /**
* 同步代码块
* @param name
*/
public void asyncMethod(String name){
synchronized (MethodSync.class){
try {
System.out.println("同步代码块!!!!"+name);
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(name + " End the sync method");
}
}
}
/**- * 非this同步代码块
- */
- public void synObject() {
- synchronized (anyString) {
- System.out.println(anyString + " IN synchronized (anyString)同步代码块");
- System.out.println(anyString + " OUT synchronized (anyString)同步代码块");
- }
- }
- }
RunnableService 调用
- public class RunnableService implements Runnable {
- /**
- * 一、
- * test1 先于 test2 执行 同步方法,但是却后于 test2 结束。这里并没有达到互斥的效果!
- * 原因是:MethodSync是实例变量,每次创建一个Test对象就会创建一个MethodSync对象,
- * synchronized 只会锁定调用method()方法的那个MethodSync对象,
- * 而这里创建的两个线程分别拥有两个不同的MethodSync对象,它们调用method方法时就没有互斥关系。
- *
- */
- /**
- * 二、
- * 当把Test.java 中的MethodSync 变量 用 static 来修饰时,执行结果如下:
- * 这里,正确实现了同步作用。原因如下:这里也创建了二个线程(Test 对象),
- * 但是每个Test对象共享MethodSync 变量,也即只有一个MethodSync 变量在两个线程中执行 method方法,
- * 这样两个线程在执行到method 方法这段代码时就会形成互斥
- *
- */
- private String name;
- private static MethodSync methodSync = new MethodSync();
- // private MethodSync methodSync = new MethodSync();
- public RunnableService(String name){
- this.name = name;
- }
- /**
- * run方法它本身启动不了多线程。多线程在实现的时候看着只是重写run方法
- * ,调用start方法启动,其实start方法里边还有其它操作:创建线程,调用run方法。
- */
- @Override
- public void run() {
- methodSync.method(name);
- }
- public static void main(String[] args) {
- // MethodSync methodSync = new MethodSync();
- // methodSync.method("你好1");
- // methodSync.method("你好2");
- Thread t1 = new Thread(new RunnableService("test 1"));
- Thread t2 = new Thread(new RunnableService("test 2"));
- t1.start();
- t2.start();
- }
- }
打印日志
- test 1 Start a sync method
- test 1 End the sync method
- test 2 Start a sync method
- test 2 End the sync method
- Process finished with exit code 0
代码 : https://gitee.com/xdymemory00/AsyncWithLock.git
继承Runnable 实现Synchronized 同步锁的更多相关文章
- Java进程与多线程+线程中的join、yield、wait等方法+synchronized同步锁使用
首先了解什么是多线程与进程 进程:是一个执行过程,动态的概念 --->会分配内存线程:是进程的一个单元,线程是系统最小的执行单元 详解: http://blog.csdn.net/luoweif ...
- Java中String做为synchronized同步锁使用详解
Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...
- 深入研究 synchronized 同步锁 作用于 静态方法 和 非静态方法 的 区别
1.前言 众所周知, synchronized 是同步锁 ,虽然在底层又细分了无锁.偏向锁.轻量级锁.自旋锁 以及重量级锁 机制, 这些底层锁知道一下原理即可 ,[想要 了解 这篇 博文 有 解释 : ...
- synchronized同步锁
在多线程的情况下,由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问.由于 ...
- 三、synchronized同步锁
一.简介 在Java多线程中,我们要实现同步串行最早接触的就是synchronized关键字. 基本语法如下: synchronized(锁) { // 代码块 } sychronized关键字的锁主 ...
- 2.synchronized同步锁
原文链接:http://blog.csdn.net/zteny/article/details/54863391 简介 synchronized是Java语言的一个关键字,用来修饰一个方法或者代码块, ...
- synchronized同步锁+单利模式
public static synchronized VolleyRequestController getInstance() { if (sInstance == null) { ...
- Java中String做为synchronized同步锁
synchronized (("" + userId).intern()) { // TODO:something } JVM内存区域里面有一块常量池,关于常量池的分配: JDK6 ...
- synchronized同步代码块锁释放
今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程锁住了. 以下是jstack -l 637 问题线程的内容. &quo ...
随机推荐
- boost之date_time库
最近开了boost库的学习,就先从日期时间库开始吧,boost的date_time库是一个很强大的时间库,用起来还是挺方便的.以下算是我学习的笔记,我把它记录下来,以后便于我复习和查阅. #inclu ...
- Resolving multicopy duplications de novo using polyploid phasing 用多倍体相位法解决多拷贝复制的新问题
抽象.虽然单分子测序系统的兴起已经实现组装复杂地区的能力空前提高在基因组中,基因组中的长节段重复仍然是装配中具有挑战性的前沿. 分段重复同时具有丰富的基因并且倾向于大的结构重排,使得它们的序列的分辨率 ...
- python多线程编程5: 条件变量同步-乾颐堂
互斥锁是最简单的线程同步机制,Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还 ...
- Zookeeper 源码(六)Leader-Follower-Observer
Zookeeper 源码(六)Leader-Follower-Observer 上一节介绍了 Leader 选举的全过程,本节讲解一下 Leader-Follower-Observer 服务器的三种角 ...
- idea注释字体倾斜的解决办法
File-->Settings-->Editor--> Color Scheme-->Language Defaults-->Comments-->Line con ...
- swoole集群 nginx配置
nginx配置文件: upstream cat { server 192.168.149.133:9502 weight=5; server 192.168.149.134:9502 weight=5 ...
- php autoload 笔记
php auotload 实现了类的延迟加载机制,需要的时候在include,平时很少用到.它的实现原理搜了一下如下(不是本人研究的结果): 检查执行器全局变量函数指针autoload_func是否为 ...
- vmware之VMware Remote Console (VMRC) SDK(三)
前两节我们介绍了vmrc sdk的基本用法.在前面的demo中,有一个关键的问题是,我们现在所作的工作都是基于局域网的,作为应用层面上,主机不会直接暴露给用户,而是通过一系列的web service服 ...
- 搭建自己的 Docker 私有仓库服务
关于 Docker 的介绍这里就省了,Docker 在其相关领域的火爆程度不亚于今年汽车行业里的特斯拉,docCloud 甚至把公司名都改成了 Docker, Inc. 好东西总是传播很快,我们现在已 ...
- C# 使用ProcessStartInfo调用exe获取不到重定向数据的解决方案
emmmmm,最近在研究WFDB工具箱,C语言写的,无奈本人C语言功底不够,只想直接拿来用,于是打算通过ProcessStartInfo来调取编译出来的exe程序获取输出. 一开始就打算偷懒,从园子里 ...