一、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. 卷积神经网络LeNet Convolutional Neural Networks (LeNet)

    Note This section assumes the reader has already read through Classifying MNIST digits using Logisti ...

  2. Element 'beans' cannot have character [children]

    在编写spring的applicationContext.xml文件时,出现了: Element 'beans' cannot have character [children], because t ...

  3. 【Android JNI】JNIEnv和JavaVM的区别

     JNI的实现可涉及两个关键类:JNIEnv和JavaVM. JavaVM:这个代表java的虚拟机.所有的工作都是从获取虚拟机的接口开始的.             第一种方式,在加载动态链接库的时 ...

  4. DRP——JDBC中的Batch

    在jdbc2.0里添加了批量处理的功能(batch),其同意将多个sql语句作为一个单元送至数据库去运行,这样做能够提高操作效率.在操作大量的数据时, ORM框架实现批量是非常慢的.我们能够使用jdb ...

  5. DHCP安装配置详解

    DHCP基于客户/服务器模式.当DHCP客户端启动时,它会自动与DHCP服务器通信,由DHCP服务器为DHCP客户端提供自动分配IP地址的服务. 当然高级的DHCP,不光只是分配地址这么简单,今天我们 ...

  6. Code a simple telnet client using sockets in python

    测试端口是否开放的python脚本 原文: https://www.binarytides.com/code-telnet-client-sockets-python/ 配置: 120.79.14.8 ...

  7. (剑指Offer)面试题6:重建二叉树

    题目: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树. 假设输入的前序遍历和中序遍历结果中都不含重复的数字. 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...

  8. MongoDB 在 Mac OSX 平台安装

    1.检查电脑是否安装 Homebrew(brew) 工具.如果没有安装,在终端执行下面命令. ruby -e "$(curl -fsSL https://raw.githubusercont ...

  9. Onvif鉴权实现方式

    Onvif鉴权实现方式 Digest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) ) gsoap中digest生成代码: int ...

  10. linux安装卸载软件

    转自:http://www.cnblogs.com/propheteia/archive/2012/06/26/2563383.html configure作用:是源码安装软件时配置环境用的 他根据你 ...