2.synchronized同步锁

原文链接:http://blog.csdn.net/zteny/article/details/54863391

简介

synchronized是Java语言的一个关键字,用来修饰一个方法或者代码块,使得目标达到线程同步的目的。

当我们希望某个方法或者代码块,同一时间只能有一个线程能够执行,即是同一时间只有一个线程能够进入该方法或者代码块,其它线程将会被阻塞直接原线程执行结束,此时我们使用该关键字。

用法

由上面的简介可以可得synchronized的两种用法,如下:

public synchronized void bar() {
    ...
}

public void foo() {
    synchronized(this) {
        ...
    }
}

1. 修饰方法

当用synchronized修饰方法时,此时其功能相当于

public void foo() {
    synchronized(this) {
        ...
    }
}

为此,我还特意看来了一下java生成class文件,发现对这两份代码生成字节码并不一样。那们为什么会这两种方式,我个人认为原因有二,当synchronized(this)的范围从方法的第一行到最后一行时,直接用synchronized修饰方法就是一种偷懒方式;其次,synchronized(this)可以有控制更小的粒度,既是只要圈住需要同步的代码可以减少的锁持有时长,提高TPS。

如果您有更准确解释,希望您能在文后评论,谢谢

2. 修饰代块码

通过修饰代块码方式来实现同步的目标时,相比修饰方法有两个优势。 
1. 只需要圈住(保护)应该圈住的代码块。被圈住的部分才会同步,其它使临界区的访问尽可能的短,从获得更好的性能。 
2. 通引用传入的变量作为同步的标量,它允许同一时刻有多个线程同时进入同步块,当它的变量值不同时。反过来,同一时刻且同一个变量值,只允许一个线程进入同步块

private Object v = new Object;
public void foo() {
    synchronized(v) {
        System.out.println(Thread.currentThread().getId() + ", enter");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) { }
        System.out.println(Thread.currentThread().getId() + ", leave");
    }
}

public void bar() {
    new Thread(() -> {
        foo();
    }).start();
    new Thread(() -> {
        foo();
    }).start()
}
它结果应该是(发生阻塞)
0, enter
0, leave
1, enter
1, leave

接下来我们稍微变一下,会出现一个不同的结果

public void bar() {
    new Thread(() -> {
        v = "123";
        foo();
    }).start();
    new Thread(() -> {
        v = "321";
        foo();
    }).start()
}
它结果是不发生阻塞的

思考

  1. 当传入的是v = 1会怎么这样呢?
  2. 当引用的是一个静态不可变变量(即static final Object v = new Object())?

    提示1,Integer a = 1; Integer b = 1;此时,a == b为true。当Integer在-128~127是全局都是同一个引用变量。 
    提示2,ClassLoader。

FAQ

如下这些细节找不到引入理由但又感得这些内容非常有价值,便用FAQ的方式强行带入。

    1. 能否在synchronized修饰的方法或代码块中发生线程上下文切换? 
      ——能。
    2. 简述synchronized具有可重入性。 
      ——在synchronized的方法或代码块内可以调用另一个带有synchronized的方法或代码块,而不发生死锁。
    3. 所有变量v写操作都发生synchronized代码块里,此时如果读操作不在synchronized代码块里,会怎么样呢? 
      ——此时变量v为弱一致性。
时间: 2024-10-06 03:40:38

2.synchronized同步锁的相关文章

synchronized同步锁详解

1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法.如:  public synchronized void accessVal(int newVal);  synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能 执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新

synchronized同步锁

在多线程的情况下,由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问.由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块.1. synchronized 方法:通过在方法声明中加入 synchr

synchronized同步代码块锁释放

今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程锁住了. 以下是jstack -l 637  问题线程的内容. "schedulerJob-t-291" #314 daemon prio=5 os_prio=0 tid=0x00007f7d64844800 nid=0x3d5 runnable [0x00007f7d3a107000] java.lang.Thread.State: RUNNABLE at

Android-Java-synchronized同步锁机制&利与弊

synchronized同步锁机制 定义锁??的方式一: package android.java.thread09; public class Test implements Runnable { @Override public void run() { /** * 定义一个锁??,这个锁是Jav内部要去判断用的,属于隐士的 看不到的 * Java内部的实现属于 ??锁机制 */ Object lock = new Object(); synchronized (lock) { /** *

java 同步锁(synchronized)

java 同步锁(synchronized) 在java中,Synchronized就是一把锁,他可以锁定一个方法,也可以锁定一个方法,我擦,其实这两个东西就是一样的.块不就是一个没有名字的方法么,方法就是一个有名字的块.本文就用块来测试.所谓锁,就是原子操作,把这个锁定的块作为一个整体,就像你上厕所,拉了就要擦屁屁,当然你也可以不擦,如果你不在意出现的问题的话.信号量Semaphore和这个Synchronized 其实实现的功能差不多,不过效率不同,使用的方式也不同.Synchronized

java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)

import java.util.concurrent.locks.*; class DuckMsg{ int size;//烤鸭的大小 String id;//烤鸭的厂家和标号 DuckMsg(){ } DuckMsg(int size, String id){ this.size=size; this.id=id; } public String toString(){ return id + " 大小为:" + size; } } class Duck{ private int

java多线程(三)——锁机制synchronized(同步语句块)

用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法之行一个长时间的任务,那么B线程必须等待比较长的时间,在这样的情况下可以使用synchronized同步语句快来解决. 一.用同步代码块解决同步方法的弊端 Task类 1 package com.weishiyao.learn.day4.testSynchorized.ep2; 2 3 public class Task { 4 5 private String getData1; 6 private Stri

002-多线程-锁-同步锁-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现

一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. synchronized结论: 1.java5.0之前,协调线程间对共享对象的访问的机制只有synchronized和volatile,但是内置锁在功能上存在一些局限性,jdk5增加了Lock以及ReentrantLock. 2.java5.0,增加了一种新的机制:显式锁ReentrantLock,注意它

单例模式(Singleton)的同步锁synchronized

单例模式,有"懒汉式"和"饿汉式"两种. 懒汉式 单例类的实例在第一次被引用时候才被初始化. public class Singleton { private static Singleton instance=null; private Singleton() { } public static Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return