synchronized关键字的使用及互斥锁的实现

synchronized关键用于多线程环境中实现操作的原子性、互斥性,确保有序的同一时间对同一资源访问。实际上,是锁的一种实现。

用法:

class ClassA{

synchronized void methodA(){//修饰非静态方法1

//临界区

}

synchronized static void methodB(){//修饰静态方法2

//临界区

}

void methodC(){

synchronized(){

//修饰代码块3,相较于修饰方法,影响的范围更小

}

}

}

修饰非静态方法时,锁定的对象是当前类的实例,修饰静态方法时,锁定的是当前类。对应于以上的1、2、3即。

synchronized(this) void …

synchronized(ClassA.class) void …

synchronized(this)…

this指的是类的一个实例,所以如果是不同实例,那么锁是无效的,无法做到资源访问的互斥。

因此,尽管在同一个类中都使用了synchronized关键字修饰资源,有时也无法做到安全的访问资源。因为资源对应的锁不是同一个。

多个相关联的资源应该作为同一个资源对应同一把锁。

例如

class ClassA{

static int val=0;

synchronized int getVal(){

return val;

}

synchronized static void addVal(){

val+=1;

}

}

以上是不安全的,因为两个synchronized所加的锁实际是不同的,不能实现资源访问的互斥。

应当改为:

class ClassA{

static int val=0;

private final Object valLock=new Object();

int getVal(){

synchronized(valLock){

return val;

}

}

static void addVal(){

synchronized(valLock){

val+=1;

}

}

}

下面再看一个转账的例子:A账户往B账户转账100,B账户往C账户转账100,每一个账户原始金额为200,线程1负责A到B,线程2负责B到C,由于线程1只对A对象加锁,线程2只对B对象加锁,两者别不互斥,可能导致两个线程读取到B中余额都是200,而最终B中余额是300.

class Account {

private int balance;

// 转账

synchronized void transfer(Account target, int amt){

if (this.balance > amt) {

this.balance -= amt;

target.balance += amt;

}

}

}

因此上面的方式不能实现线程操作的安全,应当改为如下

class Account {
  private int balance;
  // 转账
  void transfer(Account target, int amt){
    synchronized(Account.class) {
      if (this.balance > amt) {
        this.balance -= amt;
        target.balance += amt;
      }
    }
  } 
}

对类加锁,这样所有账户对象用同一把锁。

即使如此,可以实现多线程的安全操作,实际上依然是存在问题的。

如果Account类有多个子类AccountSon1 AccountSon2…,那么这些子类既属于自己的类型也同时是Account类型,在调用transfer方法时,上锁的实际是AccountSon1.class AccountSon2.class类型,依然存在安全问题。

那么此时,可以如此

final class Account{

……

}

原文地址:https://www.cnblogs.com/perfumeBear/p/11814125.html

时间: 2024-10-23 01:07:16

synchronized关键字的使用及互斥锁的实现的相关文章

关于Java中的synchronized关键字

[内容简介] 本文主要介绍Java中如何正确的使用synchronized关键字实现线程的互斥锁. [能力需求] 至少已经完整的掌握了Java的语法基础,基本的面向对象知识,及创建并启动线程. [正文] 关于synchronized关键字的使用,很多说法是“锁同一个对象”就可以确保锁是正常的,今天,有人提了一个问题,我觉得非常不错,所以与各位一起分享一下. 在这里,就不提关于线程和synchronized关键字的基本使用了,以非常传统的“银行取钱”的故事为案例,直接上代码:Ps:以下代码是直接敲

java线程总结--synchronized关键字,原理以及相关的锁

在多线程编程中,synchronized关键字非常常见,当我们需要进行"同步"操作时,我们很多时候需要该该关键字对代码块或者方法进行锁定.被synchronized锁定的代码块,只能同时有一条线程访问该代码块. 上面是很多人的认识,当然也是我之前对synchronized关键字的浅显认识,其实上面的观点存在一定的偏差.在参考了很多文章以及自己动手测试过相关代码后,我觉得有必要记录下自己对synchronized关键字的一些理解,在这个过程,会简单说说synchronized关键字的具体

悲观的并发策略——Synchronized互斥锁

volatile既然不足以保证数据同步,那么就必须要引入锁来确保.互斥锁是最常见的同步手段,在并发过程中,当多条线程对同一个共享数据竞争时,它保证共享数据同一时刻只能被一条线程使用,其他线程只有等到锁释放后才能重新进行竞争.对于java开发人员,我们最熟悉的肯定就是用synchronized关键词完成锁功能,在涉及到多线程并发时,对于一些变量,你应该会毫不犹豫地加上synchronized去保证变量的同步性. 在C/C++可直接使用操作系统提供的互斥锁实现同步和线程的阻塞和唤起,与之不同的是,j

多线程 synchronized关键字

在多线程情况下,当多个线程操作同一个资源的时候,会出现安全问题,例如脏读(一个线程咋读取变量的时候,值已经被另一个线程改变). synchronized关键字:可用来同步方法或者代码块.有关synchronized,总结一下几条. 1 synchronized关键字锁的是对象,当多个对象会创建多个锁,而达不到同步的效果. 2 只有操作公共资源的时候才需要上锁,非公共资源没必要上锁. 3 synchronized关键字拥有可重入锁. 4 异常出现的时候,会自动释放锁. 5 同步不具备继承性. 6 

阻塞锁,非阻塞锁,自旋锁,互斥锁

1.阻塞锁 多个线程同时调用同一个方法的时候,所有线程都被排队处理了.让线程进入阻塞状态进行等待,当获得相应的信号(唤醒,时间) 时,才可以进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态. public class Lock{ private boolean isLocked = false; public synchronized void lock() throws InterruptedException{ while(isLocked){ //当其他线程进来,即处

【Java并发编程】之七:使用synchronized获取互斥锁的几点说明

 在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确保在某一时刻,方法内只允许有一个线程. 采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁.每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池.任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,

转:【Java并发编程】之七:使用synchronized获取互斥锁的几点说明

转载请注明出处:http://blog.csdn.net/ns_code/article/details/17199201     在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确保在某一时刻,方法内只允许有一个线程. 采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁.每个对象都有一个monitor(锁标记)

synchronized关键字以及实例锁 类锁

Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块. 二.然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块.

JVM内部细节之一:synchronized关键字及实现细节(轻量级锁Lightweight Locking)

在C程序代码中我们可以利用操作系统提供的互斥锁来实现同步块的互斥访问及线程的阻塞及唤醒等工作.然而在Java中除了提供Lock API外还在语法层面上提供了synchronized关键字来实现互斥同步原语.那么到底在JVM内部是怎么实现synchronized关键子的呢? 一.synchronized的字节码表示: 在java语言中存在两种内建的synchronized语法:1.synchronized语句:2.synchronized方法.对于synchronized语句当Java源代码被ja