Lock-同步锁

Lock是java5提供的一个强大的线程同步机制--通过显示定义同步锁对象来实现同步。Lock可以显示的加锁、解锁。每次只能有一个线程对lock对象加锁。

Lock有ReadLock、WriteLock、ReentrantLock(可重入锁)

常用的就是ReentrantLock。代码如下:

代码逻辑:Account账户类,实现取钱的同步方法、DrawThread取钱的线程

Account:

package lock.reentrantlock2;
import java.util.concurrent.locks.*; /**
*账户类,需保持同步
*/
public class Account
{
//定义锁对象
private final ReentrantLock lock = new ReentrantLock();
private String accountNo;
private double balance; public Account(){} public Account(String accountNo , double balance)
{
this.accountNo = accountNo;
this.balance = balance;
} public void setAccountNo(String accountNo)
{
this.accountNo = accountNo;
}
public String getAccountNo()
{
return this.accountNo;
} public double getBalance()
{
return this.balance;
}
public void draw(double drawAmount)
{
lock.lock();
try
{
//账户余额大于取钱数目
if (balance >= drawAmount)
{
//吐出钞票
System.out.println(Thread.currentThread().getName() +
"取钱成功!吐出钞票:" + drawAmount);
try
{
Thread.sleep(1);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
//修改余额
balance -= drawAmount;
System.out.println("\t余额为: " + balance);
}
else
{
System.out.println(Thread.currentThread().getName() +
"取钱失败!余额不足!");
}
}
finally
{
lock.unlock();
}
} public int hashCode()
{
return accountNo.hashCode();
}
public boolean equals(Object obj)
{
if (obj != null && obj.getClass() == Account.class)
{
Account target = (Account)obj;
return target.getAccountNo().equals(accountNo);
}
return false;
}
}

  DrawThread:

package lock.reentrantlock2;

/**
* 调用account取钱
*
*/ public class DrawThread extends Thread
{
//模拟用户账户
private Account account;
//当前取钱线程所希望取的钱数
private double drawAmount; public DrawThread(String name , Account account ,
double drawAmount)
{
super(name);
this.account = account;
this.drawAmount = drawAmount;
} //当多条线程修改同一个共享数据时,将涉及到数据安全问题。
public void run()
{
account.draw(drawAmount);
}
}

  TestDraw:

package lock.reentrantlock2;

/**

 */
public class TestDraw
{
public static void main(String[] args)
{
//创建一个账户
Account acct = new Account("1234567" , 1000);
//模拟两个线程对同一个账户取钱
new DrawThread("甲" , acct , 800).start();
new DrawThread("乙" , acct , 800).start();
}
}

  运行结果:

甲取钱成功!吐出钞票:800.0
余额为: 200.0
乙取钱失败!余额不足!

使用Lock同步与同步方法很相似,都是“加锁--修改公共变量--释放锁”的模式,代码很容易看懂。两个线程对应一个Account对象,保证了两个线程对应一个lock对象,保证了同一时刻只有一个线程进入临界区。Lock还包含太容易Lock(),以及试图获取可中断锁的lockInterruptibly(),获取超时失效锁的tryLock(long,TimeUnit)等方法。

ReentrantLock锁具有可重入性可以对已被加锁的ReentrantLock锁再次加锁,线程每次调用lock()加锁后,必须显示的调用unlock来释放锁,有几个lock就对应几个unlock。还有把unlock放在finally代码块中,Lock在发生异常时也是不释放锁的,所以在finally中释放更安全。

只是对Lock简单说明了下,为下一篇线程通信打基础。

Lock同步锁--线程同步的更多相关文章

  1. Python并发编程-进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

  2. Python3 进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

  3. 001-多线程-锁-架构【同步锁、JUC锁】

    一.概述 Java中的锁,可以分为"同步锁"和"JUC包中的锁". 1.1.同步锁 即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁 ...

  4. Java线程状态及同步锁

    线程的生命历程 线程的五大状态 创建状态:简而言之,当创建线程对象的代码出现的时候,此时线程就进入了创建状态.这时候的线程只是行代码而已.只有调用线程的start()方法时,线程的状态才会改变,进入就 ...

  5. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  6. C# 多线程(二) 线程同步基础

    本系列的第一篇简单介绍了线程的概念以及对线程的一些简单的操作,从这一篇开始讲解线程同步,线程同步是多线程技术的难点.线程同步基础由以下几个部分内容组成 1.同步要领(Synchronization E ...

  7. c#编程-线程同步

    线程同步 上一篇介绍了如何开启线程,线程间相互传递参数,及线程中本地变量和全局共享变量区别. 本篇主要说明线程同步. 如果有多个线程同时访问共享数据的时候,就必须要用线程同步,防止共享数据被破坏.如果 ...

  8. .net中的线程同步基础(搬运自CLR via C#)

    线程安全 此类型的所有公共静态(Visual Basic 中为 Shared)成员对多线程操作而言都是安全的.但不保证任何实例成员是线程安全的. 在MSDN上经常会看到这样一句话.表示如果程序中有n个 ...

  9. C#线程同步(5)- 信号量 Semaphore

    文章原始出处 http://xxinside.blogbus.com/logs/47617134.html 预备知识:C#线程同步(1)- 临界区&Lock,C#线程同步(2)- 临界区&am ...

随机推荐

  1. matlab 读取excel

    clear;clc; tic;%启动计时器,计算程序运行时间 a=xlsread('C:\Documents and Settings\Administrator\桌面\data.xls');b=a( ...

  2. Python语言特性之2:元类

    问题:Python中的元类(metaclasses)是什么?一般使用它干什么? 原地址:http://stackoverflow.com/questions/100003/what-is-a-meta ...

  3. vue-resource 拦截器使用

    在vue项目使用vue-resource的过程中,临时增加了一个需求,需要在任何一个页面任何一次http请求,增加对token过期的判断,如果token已过期,需要跳转至登录页面.如果要在每个页面中的 ...

  4. STM32 DMA使用详解

    DMA部分我用到的相对简单,当然,可能这是新东西,我暂时还用不到它的复杂功能吧.下面用问答的形式表达我的思路. DMA有什么用? 直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数 ...

  5. C#中是否可以继承String类

    C#中是否可以继承String类? 答:String类是sealed类故不可以继承. 当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承. 在下面的示例中,类 HoverTree ...

  6. 关于C#基础

    前几天帮人做个社交网站,还是用的控件方式,不过学习了ajax和一般处理程序ashx后,也用在了里面一些,今天回来继续写博客.继续上次总结下基础知识,学的内容多,总结的可能比较杂乱,分条总结为平时能自己 ...

  7. Mysql高并发优化

    一.数据库结构的设计 1.数据行的长度不要超过8020字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率. 2.能够用数字类型的字段尽量选择数字类型而不用字符串类型的 ...

  8. Web.config配置文件详解

    整理了一下ASP.NET Web.config配置文件的基本使用方法.很适合新手参看,由于Web.config在使用很灵活,可以自定义一些节点.所以这里只介绍一些比较常用的节点. <?xml v ...

  9. UITextView 文本垂直居中

    var center=textView.Bounds.Size.Height - textView.ContentSize.Height; center = center < ? : cente ...

  10. Oracle数据库,非空约束、主键约束、外键约束、唯一约束

    非空约束:设置列时,可为空默认可为空,去掉对号之后设置数据不可为空: 唯一约束:在键中设置,唯一约束名称.类型Unique.列名:设置应用完成之后,此列数据具有唯一性:即数据不可重复(类型:Uniqu ...