一、Synchronized

synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争某个资源的时候会有先后顺序。在java中有三种写synchronized的方式:

第一种:写在普通方法的前面,这种表示对实例对象加锁第二种:写在静态方法前面,这种表示对类对象加锁第三种:写在代码块中,锁是Synchonized括号里配置的对象(可能是实例对象,也可能是类对象)

总体说来就2种,一种就是锁实例对象,一种锁类对象。

锁实例对象就是当多个线程同时操作这个实例对象(针对的是特定的实例对象)的时候必须先获取锁,如果无法获取锁,则必须处于等待状态,而和锁类对象区别是,当多个线程同时操作的时候,任何以这个类对象实例化的对象都要获取锁才能操作。

看下面的例子:

public class Synchronized_Test {
public static void main(String[] args){
Thread t1=new Thread(new MyRunnable());
Thread t2=new Thread(new MyRunnable());
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable{
private synchronized void synchMethodTest(){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+"synchMethodTest: "+i);
}
public void run() {
synchMethodTest();
}
}

其输出结果为:

Thread-0synchMethodTest: 0
Thread-1synchMethodTest: 0
Thread-0synchMethodTest: 1
Thread-1synchMethodTest: 1
Thread-0synchMethodTest: 2
Thread-1synchMethodTest: 2
Thread-0synchMethodTest: 3
Thread-1synchMethodTest: 3
Thread-0synchMethodTest: 4
Thread-1synchMethodTest: 4
Thread-0synchMethodTest: 5
Thread-1synchMethodTest: 5
Thread-0synchMethodTest: 6
Thread-1synchMethodTest: 6
Thread-0synchMethodTest: 7
Thread-1synchMethodTest: 7
Thread-0synchMethodTest: 8
Thread-1synchMethodTest: 8
Thread-0synchMethodTest: 9
Thread-1synchMethodTest: 9

因为synchronized是写在普通方法前,是对特定的实例对象加锁,t1,t2为两个不同的实例,
所以他们在执行synchronized方法时并不会互相阻塞对方。

如果将synchronized方法改成static方法,那么就是针对类对象加锁,任何以这个类对象实例化的对象都要获取锁才能操作,
t1,t2虽然是两个不同的实例,但都是同一个类对象的实例,所以当t1取得锁开始执行synchronized方法后,就会阻塞t2,
t2需要取得锁之后才能执行,如下:

public class Synchronized_Test {
public static void main(String[] args){
Thread t1=new Thread(new MyRunnable());
Thread t2=new Thread(new MyRunnable());
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable{
private synchronized static void synchMethodTest(){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+"synchMethodTest: "+i);
}
public void run() {
synchMethodTest();
}
}

输出结果为:

Thread-0synchMethodTest: 0
Thread-0synchMethodTest: 1
Thread-0synchMethodTest: 2
Thread-0synchMethodTest: 3
Thread-0synchMethodTest: 4
Thread-0synchMethodTest: 5
Thread-0synchMethodTest: 6
Thread-0synchMethodTest: 7
Thread-0synchMethodTest: 8
Thread-0synchMethodTest: 9
Thread-1synchMethodTest: 0
Thread-1synchMethodTest: 1
Thread-1synchMethodTest: 2
Thread-1synchMethodTest: 3
Thread-1synchMethodTest: 4
Thread-1synchMethodTest: 5
Thread-1synchMethodTest: 6
Thread-1synchMethodTest: 7
Thread-1synchMethodTest: 8
Thread-1synchMethodTest: 9

t1执行完成,释放synchronized锁后,t2才能执行。如果在代码块中对类对象也是一样:

class MyRunnable implements Runnable{
private void synchMethodTest(){
synchronized (MyRunnable.class){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+"synchMethodTest: "+i);
}
}
public void run() {
synchMethodTest();
}
}

注意:
      类方法中,synchronized锁住的是对象this,只有调用同一个对象的方法才需要获取锁。同时,
同一个对象中所有加了synchronize的方法只能一次调用一个;
      静态方法中,synchronized锁的是整个类对象,类似于(X.class),该类中所有加了synchronized的静态方法,一次只能调用一个。
比较下面两个例子:

public class Synchronized_Test {
public static void main(String[] args){
Method method=new Method();
Thread t1=new Thread(new MyRunnable1(method));
Thread t2=new Thread(new MyRunnable2(method));
t1.start();
t2.start();
}
}
class Method{
public synchronized void Method1(){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+" Method1: "+i);
}
public synchronized void Method2(){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+" Method2 "+i);
}
}
class MyRunnable1 implements Runnable{
Method method;
MyRunnable1(Method method){
this.method=method;
}
public void run() {
method.Method1();
}
}
class MyRunnable2 implements Runnable{
Method method;
MyRunnable2(Method method){
this.method=method;
}
public void run(){
method.Method2();
}
}

输出为:

Thread-0 Method1: 0
Thread-0 Method1: 1
Thread-0 Method1: 2
Thread-0 Method1: 3
Thread-0 Method1: 4
Thread-0 Method1: 5
Thread-0 Method1: 6
Thread-0 Method1: 7
Thread-0 Method1: 8
Thread-0 Method1: 9
Thread-1 Method2 0
Thread-1 Method2 1
Thread-1 Method2 2
Thread-1 Method2 3
Thread-1 Method2 4
Thread-1 Method2 5
Thread-1 Method2 6
Thread-1 Method2 7
Thread-1 Method2 8
Thread-1 Method2 9

因为锁住的整个Method对象,在t1执行method1时,给method对象加锁,当t2要执行method2时,因为时synchronized方法,
所以首先要取得method对象的锁,才能执行。

public class Synchronized_Test {
public static void main(String[] args){
Method method=new Method();
Thread t1=new Thread(new MyRunnable1(method));
Thread t2=new Thread(new MyRunnable2(method));
t1.start();
t2.start();
}
}
class Method{
public synchronized void Method1(){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+" Method1: "+i);
}
public void Method2(){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+" Method2 "+i);
}
}
class MyRunnable1 implements Runnable{
Method method;
MyRunnable1(Method method){
this.method=method;
}
public void run() {
method.Method1();
}
}
class MyRunnable2 implements Runnable{
Method method;
MyRunnable2(Method method){
this.method=method;
}
public void run(){
method.Method2();
}
}

输出为:

Thread-0 Method1: 0
Thread-1 Method2 0
Thread-0 Method1: 1
Thread-1 Method2 1
Thread-0 Method1: 2
Thread-1 Method2 2
Thread-0 Method1: 3
Thread-1 Method2 3
Thread-0 Method1: 4
Thread-1 Method2 4
Thread-0 Method1: 5
Thread-1 Method2 5
Thread-0 Method1: 6
Thread-1 Method2 6
Thread-1 Method2 7
Thread-1 Method2 8
Thread-1 Method2 9
Thread-0 Method1: 7
Thread-0 Method1: 8
Thread-0 Method1: 9

从结果可以看到,t1并没有阻塞t2的运行,因为t2执行的method2方法不带synchronized,所以在执行时并不需要先获得method对象的锁,执行的过程中也就不存在阻塞的情况。

二、wait、notify和notifyAll

wait、notify、notifyAll是Object对象的属性,并不属于线程。我们先解释这三个的一个很重要的概念

wait:使持有该对象的线程把该对象的控制权交出去,然后处于等待状态(这句话很重要,也就是说当调用wait的时候会释放锁并处于等待的状态)notify:通知某个正在等待这个对象的控制权的线程可以继续运行(这个就是获取锁,使自己的程序开始执行,最后通过notify同样去释放锁,并唤醒正在等待的线程)notifyAll:会通知所有等待这个对象控制权的线程继续运行(和上面一样,只不过是唤醒所有等待的线程继续执行)Obj.wait()与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait与notify是针对已经获取了Obj锁的对象来进行操作

下面来看一个生产者消费者模型,他们有一个缓冲区,缓冲区有最大限制,当缓冲区满的时候,生产者是不能将产品放入到缓冲区里面的,当然,当缓冲区是空的时候,消费者也不能从中拿出来产品,这就涉及到了在多线程中的条件判断,java中提供了wait和notify方法,他们可以在线程不满足要求的时候让线程让出来资源等待,当有资源的时候再notify他们让他们继续工作。

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
class EventStorage {
private int maxSize;
private List<date> storage;
public EventStorage() {
maxSize = 10;
storage = new LinkedList<date>();
}
public synchronized void set() {
while(storage.size() == maxSize) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.add(new Date());
System.out.println("Set: "+storage.size());
notifyAll();
}
public synchronized void get() {
while(storage.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Get: "+storage.size()+" "+((LinkedList<date>)storage).poll());
notifyAll();
}
}
class Producer implements Runnable {
private EventStorage storge;
public Producer(EventStorage storage) {
this.storge = storage;
}
public void run() {
for(int i = 0; i < 100; i++) {
storge.set();
}
}
}
class Consumer implements Runnable {
private EventStorage storage;
public Consumer(EventStorage storage) {
this.storage = storage;
}
public void run() {
for (int i = 0; i < 100; i++) {
storage.get();
}
}
}
public class ProducerAndConsumer {
public static void main(String[] args){
EventStorage eventStorage=new EventStorage();
Thread t1=new Thread(new Producer(eventStorage));
Thread t2=new Thread(new Consumer(eventStorage));
t1.start();
t2.start();
}
}

JAVA多线程之Synchronized、wait、notify实例讲解的更多相关文章

  1. JAVA多线程之synchronized和volatile实例讲解

    在多线程中,提到线程安全.线程同步,我们经常会想到两个关键字:volatile和synchronized,那么这两者有什么区别呢? 1. volatile修饰的变量具有可见性 volatile是变量修 ...

  2. java 多线程之synchronized wait/notify解决买票问题

    一.Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable):当调用线程对象的st ...

  3. java多线程之wait和notify协作,生产者和消费者

    这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...

  4. Java多线程之wait、notify/notifyAll 详解,用wait 和notifyAll 以及synchronized实现阻塞队列,多线程拓展之ReentrantLock与Condition

    前言:这几天看了很多关于多线程的知识,分享一波.(但是目前接触的项目还未用到过,最多用过线程池,想看线程池 请看我之前的博客) 关于基本的理论等 参考如下: https://www.cnblogs.c ...

  5. (二)java多线程之synchronized

    本人邮箱: kco1989@qq.com 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kco github: https://github.com/kco198 ...

  6. JAVA多线程之Synchronized关键字--对象锁的特点

    一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...

  7. Java多线程之synchronized及其优化

    Synchronized和同步阻塞synchronized是jvm提供的同步和锁机制,与之对应的是jdk层面的J.U.C提供的基于AbstractQueuedSynchronizer的并发组件.syn ...

  8. Java多线程之synchronized详解

    目录 synchronized简介 同步的原理 对象头与锁的实现 锁的优化与升级 Monitor Record 锁的对比 synchronized简介 synchronized关键字,一般称之为&qu ...

  9. Java多线程之Wait()和Notify()

    1.Wait()和Notify.NotifyAll都是Object的方法 2.多线程的协作是通过控制同一个对象的Wait()和Notify()完成 3.当调用Wait()方法时,当前线程进入阻塞状态, ...

随机推荐

  1. faked 一个用于 mock 后端 API 的轻量工具

    一.简介 faked 是一个在前端开发中用于 mock 服务端接口的模块,轻量简单,无需要在本地启动 Server 也无需其它更多的资源,仅在浏览器中完成「请求拉截」,配合完整的「路由系统」轻而易举的 ...

  2. 数学图形(1.40)T_parameter

    不记得在哪搞了个数学公式生成的图形. vertices = t = to (*PI) r = 2.0 x = r*(*cos(t) - cos(*t)) y = r*(*sin(t) - sin(*t ...

  3. css hack 和问题

    浏览器特定的选择 当你想改变一个样式在一个浏览器而不是其他这些选择是非常有用的. IE 6及以下    * html {} IE 7及以下    *:first-child+html {} * htm ...

  4. 算法导论-矩阵乘法-strassen算法

    目录 1.矩阵相乘的朴素算法 2.矩阵相乘的strassen算法 3.完整测试代码c++ 4.性能分析 5.参考资料 内容 1.矩阵相乘的朴素算法 T(n) = Θ(n3) 朴素矩阵相乘算法,思想明了 ...

  5. HDU 4528 BFS 小明系列故事——捉迷藏

    原题直通车:HDU 4528 小明系列故事——捉迷藏 分析: 标记时加两种状态就行. 代码: #include<iostream> #include<cstring> #inc ...

  6. jquery ajax方式直接提交整个表单

    $.ajax({ type: "POST", url: url, data: $('#form1').serialize(), success: function(msg){ al ...

  7. 转:Android应用开发性能优化完全分析

    转自:http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜 ...

  8. MatLab2012b/MatLab2013b 分类器大全(svm,knn,随机森林等)

    train_data是训练特征数据, train_label是分类标签.Predict_label是预测的标签.MatLab训练数据, 得到语义标签向量 Scores(概率输出). 1.逻辑回归(多项 ...

  9. Sn.exe(强名称工具)

    Sn.exe(强名称工具) .NET Framework 4.5   强名称工具 (Sn.exe) 有助于使用强名称对程序集进行签名. Sn.exe 提供了用于密钥管理.签名生成和签名验证的选项. 强 ...

  10. eclipse 发布签名APK图文讲解

    eclipse 发布 签名android 程序 1 在项目上右键 export 2 export android application 3 第一次发布 要创建一个新的keystore 4 填写key ...