一、同步方法

  即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类。

二、同步代码块

  即有synchronized关键字修饰的语句块。 被synchronized关键字修饰的语句块会自动被加上内置锁,从而实现同步
    代码如: 
synchronized(object){
}
   注:同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。 

线程在执行同步方法时是具有排它性的。当任意一个线程进入到一个对象的任意一个同步方法时,这个对象的所有同步方法都被锁定了,在此期间,其他任何线程都不能访问这个对象的任意一个同步方法,直到这个线程执行完它所调用的同步方法并从中退出,从而导致它释放了该对象的同步锁之后。在一个对象被某个线程锁定之后,其他线程是可以访问这个对象的所有非同步方法的。

同步块:同步块是通过锁定一个指定的对象,来对同步块中包含的代码进行同步;而同步方法是对这个方法块里的代码进行同步,而这种情况下锁定的对象就是同步方法所属的主体对象自身。如果这个方法是静态同步方法呢?那么线程锁定的就不是这个类的对象了,也不是这个类自身,而是这个类对应的java.lang.Class类型的对象。同步方法和同步块之间的相互制约只限于同一个对象之间,所以静态同步方法只受它所属类的其它静态同步方法的制约,而跟这个类的实例(对象)没有关系。

如果一个对象既有同步方法,又有同步块,那么当其中任意一个同步方法或者同步块被某个线程执行时,这个对象就被锁定了,其他线程无法在此时访问这个对象的同步方法,也不能执行同步块。

synchronized 关键字用于保护共享数据。请大家注意“共享数据”,你一定要分清哪些数据是共享数据,请看下面的例子:

synchronized的目的是使同一个对象的多个线程,在某个时刻只有其中的一个线程可以访问这个对象的synchronized 数据。每个对象都有一个“锁标志”,当这个对象的一个线程访问这个对象的某个synchronized 数据时,这个对象的所有被synchronized 修饰的数据将被上锁(因为“锁标志”被当前线程拿走了),只有当前线程访问完它要访问的synchronized 数据时,当前线程才会释放“锁标志”,这样同一个对象的其它线程才有机会访问synchronized 数据。

三、wait与notify

wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

四、使用特殊域变量(volatile)实现线程同步

    a.volatile关键字为域变量的访问提供了一种免锁机制
    b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新
    c.因此每次使用该域就要重新计算,而不是使用寄存器中的值 
    d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量 
     

五、使用重入锁实现线程同步

    在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。 
    ReentrantLock类是可重入、互斥、实现了Lock接口的锁,它与使用synchronized方法和块具有相同的基本行为和语义,并且扩展了其能力。
 ReenreantLock类的常用方法有:
ReentrantLock() : 创建一个ReentrantLock实例
lock() : 获得锁
unlock() : 释放锁
注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用 
        
private Lock lock = new ReentrantLock();
lock.lock();
共享资源
lock.unlock();
    注:关于Lock对象和synchronized关键字的选择: 
        a.最好两个都不用,使用一种java.util.concurrent包提供的机制,能够帮助用户处理所有与锁相关的代码。 
        b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码 
        c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁 
 

六、使用局部变量实现线程同步

    如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。
     ThreadLocal 类的常用方法
ThreadLocal() : 创建一个线程本地变量
get() : 返回此线程局部变量的当前线程副本中的值
initialValue() : 返回此线程局部变量的当前线程的"初始值"
set(T value) : 将此线程局部变量的当前线程副本中的值设置为value
  
 public class Bank{
//使用ThreadLocal类管理共享变量account
private static ThreadLocal<Integer> account = new ThreadLocal<Integer>(){
@Override
protected Integer initialValue(){
return 100;
}
};

   public void save(int money){
account.set(account.get()+money);
}
public int getAccount(){
return account.get();
}
}
    注:ThreadLocal与同步机制 
        a.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。 
        b.前者采用以"空间换时间"的方法,后者采用以"时间换空间"的方式
 

七、使用阻塞队列实现线程同步

前面5种同步方式都是在底层实现的线程同步,但是我们在实际开发当中,应当尽量远离底层结构。 使用javaSE5.0版本中新增的java.util.concurrent包将有助于简化开发。 本小节主要是使用LinkedBlockingQueue<E>来实现线程的同步 LinkedBlockingQueue<E>是一个基于已连接节点的,范围任意的blocking queue。 队列是先进先出的顺序(FIFO),关于队列以后会详细讲解~LinkedBlockingQueue 类常用方法 LinkedBlockingQueue() : 创建一个容量为Integer.MAX_VALUE的LinkedBlockingQueue put(E e) : 在队尾添加一个元素,如果队列满则阻塞 size() : 返回队列中的元素个数 take() : 移除并返回队头元素,如果队列空则阻塞代码实例: 实现商家生产商品和买卖商品的同步

注:BlockingQueue<E>定义了阻塞队列的常用方法,尤其是三种添加元素的方法,我们要多加注意,当队列满时:

  add()方法会抛出异常

  offer()方法返回false

  put()方法会阻塞

7.使用原子变量实现线程同步

需要使用线程同步的根本原因在于对普通变量的操作不是原子的。

那么什么是原子操作呢?原子操作就是指将读取变量值、修改变量值、保存变量值看成一个整体来操作即-这几种行为要么同时完成,要么都不完成。在java的util.concurrent.atomic包中提供了创建了原子类型变量的工具类,使用该类可以简化线程同步。其中AtomicInteger 表可以用原子方式更新int的值,可用在应用程序中(如以原子方式增加的计数器),但不能用于替换Integer;可扩展Number,允许那些处理机遇数字类的工具和实用工具进行统一访问。

AtomicInteger类常用方法:

AtomicInteger(int initialValue) : 创建具有给定初始值的新的

AtomicIntegeraddAddGet(int dalta) : 以原子方式将给定值与当前值相加

get() : 获取当前值

Java多线程同步方法的更多相关文章

  1. Java多线程同步方法Synchronized和volatile

    11 同步方法  synchronized – 同时解决了有序性.可见性问题  volatile – 结果可见性问题 12 同步- synchronized synchronized可以在任意对象上加 ...

  2. “全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程

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

  3. “全栈2019”Java多线程第二十章:同步方法产生死锁的例子

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

  4. Java多线程-线程的同步(同步方法)

    线程的同步是保证多线程安全访问竞争资源的一种手段.线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源.什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些 ...

  5. 【Java多线程】线程同步方法概览

    一:使用syncrhoized内置锁实现同步 使用互斥来实现线程间的同步,保证共享数据在同一时刻只被一个线程使用.Java中最基本的互斥手段就是syncrhoized关键字. syncrhoized的 ...

  6. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  7. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  8. Java多线程干货系列—(一)Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  9. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

随机推荐

  1. HDU 2154:跳舞毯

    跳舞毯 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  2. mschart 使用心得和部署。

    参考: http://www.cnblogs.com/suguoqiang/archive/2013/01/16/2862945.html 1.在统计时可能需要多条数据,需要整合数据源 Chart1. ...

  3. JProfiler 8(一个很好的java性能监控工具) 下载和注册码

    windows x64 zip下载地址:http://download-aws.ej-technologies.com/jprofiler/jprofiler_windows-x64_8_0_1.zi ...

  4. GNU Radio: Synchronization and MIMO Capability with USRP Devices

    Application Note Synchronization and MIMO Capability with USRP Devices Ettus Research Introduction S ...

  5. Ubuntu 16.04 natural scrolling

    http://ubuntuhandbook.org/index.php/2016/05/install-ubuntu-tweak-in-ubuntu-16-04/ download ubuntu-tw ...

  6. sdk manager 代理,解决下载速度慢的问题

    原文:http://blog.csdn.net/android_panda/article/details/18598883 地址:mirrors.neusoft.edu.cn 端口:80 要勾选:F ...

  7. debian的甘特图工具

    sudo apt-get install planner

  8. Train-Alypay-Cloud:蚂蚁大数据平台培训开课通知(第三次)

    ylbtech-Train-Alypay-Cloud:蚂蚁大数据平台培训开课通知(第三次) 1.返回顶部 1. 您好! 很高兴通知您,您已经成功报名将于蚂蚁金服计划在2018年2月28日- 2018年 ...

  9. 精《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #5 使用checkpatch.pl检查补丁的格式

    HACK #5 使用checkpatch.pl检查补丁的格式 本节介绍发布前检查补丁格式的方法.Linux内核是由多个开发者进行开发的.因此,为了保持补丁评估与源代码的可读性,按照统一的规则进行编写是 ...

  10. Linux Storage Stack Diagram存储堆栈图

    这是一个描述非常好的存储栈,版本为:Linux Storage Stack Diagram v4.10,我在这里转载下图片,可以提升大家对存储栈的理解. https://www.thomas-kren ...