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

2、除了方法前使用synchronized关键字,还可以用于方法中的某个区块中,表示这个区块的资源是互斥访问的,用法是:
synchronized(this){/代码块/}
它的作用域是当前对象。
3、synchronized关键字是不能继承的,也就是说,基类中的synchronized fun(),在继承类中并不是自动的synchronized fun(),而是变成了 fun(),继承需要你显示地指定它的某个方法为synchronized 方法。

总的来说,synchronized关键字可以作为函数的修饰符,也可以作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细致的分类,synchronized关键字可用于instence变量,object reference(对象引用),static函数和class literals(类名称字面常量)身上。

在进一步阐述之前,我们需要明确以下几点:
A:无论synchronized关键字加在方法还是对象上,它取得锁都是对象,而不是把一段代码或者函数当做锁,而且同步方法还可能被其他线程的对象访问,(说明:其他线程的对象是指:和当前对象是同一个类 但是却不是同一个实例)。
B:每个对象只有一把锁与之相关联。
C:实现同步是需要很大的系统开销作为代价的,甚至可能造成死锁,所以尽可能编码无所谓的同步控制。

接下来分析下:synchronized关键字用在不同的地方队代码产生的影响:
假设:P1、P2是同一个类的不同对象,这个类定义了以下几种情况的同步块或同步方法,P1、P2都可以调用它们。
1、把synchronized关键字当做函数修饰符使用时,代码如下:

 public synchronized void method_A(){
//......
}

这就是同步方法,那这个时候,synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法的对象。也就是说当一个对象P1在不同的线程中执行这个同步方法时,它们之间会互斥,达到同步的效果。但是这个对象所属的class类的其他实例对象,比如P2却可以随意调用这个被synchronized修饰的同步方法。根本原因:
synchroonized关键字修饰方法时,这个方法被叫做同步方法,同步的方法锁住的对象是,同步方法所在类的那个实例化对象,但是类的实例化可以有无数个,那么到底锁住的是哪个呢?答案是当前调用synchronized修饰方法的那个对象。
由于每个对象都会被JVM分配一把锁,一个类有多个实例化对象,同一个对象可以被多个线程调用,正在被锁的是“当前线程队当前这个对象的所有synchronized方法或synchronized块的使用权限”。一旦某个线程正在使用,其他线只能处于排队等待状态,而不可使用。
上边的示例代码等同于如下代码:

 public void method_A()
{
synchronized (this) // synchronized同步块
{
//…..
}
}

分析上面的代码:
synchronized代码块中:this指的是什么?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱:

2、同步代码块,实例代码如下:

 public void method3(SomeObject so) {
  synchronized(so)
  {
    //…..同步代码块
  }
}

这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

 class Foo implements Runnable
{
private byte[] lock = new byte[0]; // 特殊的instance变量
public void methodA()
{
synchronized(lock) { //… }
}
//…..
}

注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
3、将synchronized作用于static 函数,示例代码如下:

 Class Foo
{
  public synchronized static void methodAAA() // 同步的static 函数
  {
  //….
  }
  public void methodBBB()
  {
    synchronized(Foo.class) // class literal(类名称字面常量)
  }
}

代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。
可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。B方法的锁是Obj这个对象,而A的锁是Obj所属的那个Class。
总结一下:
1、线程同步的目的是为了保护多个线程访问一个资源时对资源的破坏。
2、线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他非同步方法。
3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
4、对于同步,要时刻清醒在哪个对象上同步,这是关键。
5、编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对“原子”操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。
6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。真让你写个死锁程序,不一定好使,呵呵。但是,一旦程序发生死锁,程序将死掉。

多线程学习-基础( 九)线程同步Synchronized关键字的更多相关文章

  1. 多线程学习-基础( 十一)synchronized关键字修饰方法的简单案例

    一.本案例设计到的知识点 (1)Object的notify(),notifyAll(),wait()等方法 (2)Thread的sleep(),interrupt(). (3)如何终止线程. (4)如 ...

  2. Java多线程系列--“基础篇”04之 synchronized关键字

    概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...

  3. “全栈2019”Java多线程第十六章:同步synchronized关键字详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  4. [03] 线程同步 synchronized

    1.线程同步概述 线程之间有可能共享一些资源,比如内存.文件.数据库等.多个线程同时读写同一份共享资源时,就可能引起冲突,所以引入了线程的"同步"机制. 所谓同步,就是说线程要有先 ...

  5. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  6. C++11并发学习之三:线程同步(转载)

    C++11并发学习之三:线程同步 1.<mutex> 头文件介绍 Mutex又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mutex> 头文 ...

  7. Java基础教程——线程同步

    线程同步 synchronized:同步的 例:取钱 不做线程同步的场合,假设骗子和户主同时取钱,可能出现这种情况: [骗子]取款2000:账户余额1000 [户主]取款2000:账户余额1000 结 ...

  8. Java多线程:线程同步与关键字synchronized

    一.同步的特性1. 不必同步类中所有的方法, 类可以同时拥有同步和非同步方法.2. 如果线程拥有同步和非同步方法, 则非同步方法可以被多个线程自由访问而不受锁的限制. 参见实验1:http://blo ...

  9. java 多线程:Thread 并发线程: 方法同步synchronized关键字,与static的结合

    1.方法内的变量是安全的 方法内定义的变量,每个变量对应单独的内存变量地址,多个线程之间相互不影响.多个线程之间的变量根本没有一毛钱关系 public class ThreadFuncVarSafe ...

随机推荐

  1. 从零开始的acm竞赛生涯

    经过了一段时间的训练,自己的成绩还是很不理想.回首过往,感觉自己还是练得太少,一直没有进入状态,缺乏硬怼出题的能力,思维也不够快,赛场上各种被卡题.可以说,我之前的训练有些仓促,还没有达到入门的水准, ...

  2. Python之用虚拟环境隔离项目,并重建依赖关系

    下面将以安装django和mysqlclient介绍如何用虚拟环境隔离项目,并重建依赖关系.操作系统:windows 10:python版本:python3.7 1. 安装python虚拟环境 (1) ...

  3. 日志收集系统搭建-BELK

    前言 日志是我们分析系统运行情况.问题定位.优化分析等主要数据源头.目前,主流的业务系统都采用了分布式.微服务的形式.如果想要查看日志,就需要从不同的节点上去查看,而且对于整个业务链路也非常不清晰.因 ...

  4. 表有外键所以delete报错了,这里有2种办法处理:

    表有外键所以delete报错了,这里有2种办法处理: (1)      临时设置外键失效 (2)      删除表涉及到的外键的表的数据 2.外键失效的处理方案 mysql> SET FOREI ...

  5. 布同:使用ghost备份或者还原的往事

    我大学的时候经常折腾电脑,安装了不少莫名其妙的东西.当时对各种小软件特别感兴趣,本着毕业后可以做客户端开发的初衷去做事情.不过很多小软件会恶意安装各种东西,修改注册表,时间一长就会导致C盘很臃肿,必须 ...

  6. 【转】 Pro Android学习笔记(八六):了解Package(5):使用lib

    目录(?)[-] 在项目中使用lib 源代码 了解一些机制 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowin ...

  7. SQL基础(3)

    SQL FULL JOIN (1)SQL FULL JOIN关键字 只要其中某个表存在匹配,FULL JOIN 关键字就会返回行. (2)语法 SELECT column_name(s) FROM t ...

  8. Tiny4412 Linux 内核启动流程

    Linux内核的启动分为压缩内核和非压缩内核两种,这里我们以压缩内核为例.压缩内核运行时,将运行一段解压缩程序,得到真正的内核镜像,然后跳转到内核镜像运行.此时,Linux进入非压缩内核入口,在非压缩 ...

  9. Github中README.md换行

    两个以上的空格,然后回车.我date

  10. 环境变量,include搜索路径,lib库搜索路径

    环境变量 系统环境变量 我们知道,我们经常要设置一些环境变量,系统环境变量我们非常容易理解.其实我们在windows中经常容易接触.其实环境变量是一个非常广泛的一个概念,它与web应用程序中的web. ...