49--多线程(八)

Lock(锁)

1.从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同 步锁对象来实现同步。同步锁使用Lock对象充当。
2.java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的 工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象 加锁,线程开始访问共享资源之前应先获得Lock对象。
3.ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和 内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以 显式加锁、释放锁。
实例:

package com.qwy13;

import java.util.concurrent.locks.ReentrantLock;

class Window extends Thread {
	private static int ticket = 10;
	//1.创建锁对象:注意需要加static
	private static ReentrantLock reet= new ReentrantLock();
	@Override
	public void run() {
		//为了能将票卖完,这里多循环了
		for(int i=0;i<1000;i++){
			sell();
		}

	}
	
	private  void sell() {

		try {
			//2.显示的加锁
			reet.lock();
			if (ticket > 0) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "卖出票号:" + ticket--);
			}
		} finally{
			//显示释放锁
			reet.unlock();
		}

	}
}

public class TestTick {
	public static void main(String[] args) {
		// 创建三个线程对象,表示三个窗口
		Window w1 = new Window();
		Window w2 = new Window();
		Window w3 = new Window();
		// 给三个窗口起名(设置线程名称)
		w1.setName("窗口A");
		w2.setName("窗口B");
		w3.setName("窗口C");
		// 启动线程
		w1.start();
		w2.start();
		w3.start();

	}
}

可能的运行结果:
窗口A卖出票号:10
窗口A卖出票号:9
窗口A卖出票号:8
窗口A卖出票号:7
窗口B卖出票号:6
窗口C卖出票号:5
窗口C卖出票号:4
窗口C卖出票号:3
窗口A卖出票号:2
窗口A卖出票号:1

实例:

package com.qwy14;

import java.util.concurrent.locks.ReentrantLock;

class Window implements Runnable {

	private int ticket = 10;
	private ReentrantLock lock= new ReentrantLock();
	@Override
	public void run() {
		while(true){
			try {
				lock.lock();//手动加锁
				if(ticket>0){
					try {
						Thread.currentThread().sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "卖出票号:" + ticket--);
				}else{
					break;
				}
			} finally {
				lock.unlock();//手动释放锁
			}
		}

	}
	

}

public class TestTickit {
	public static void main(String[] args) {
		// 创建Runnable接口实例
		Window w1 = new Window();
		// 创建三个线程表示三个窗口
		Thread t1 = new Thread(w1);
		Thread t2 = new Thread(w1);
		Thread t3 = new Thread(w1);
		// 给线程起名
		t1.setName("窗口A");
		t2.setName("窗口B");
		t3.setName("窗口C");

		// 启动线程
		t1.start();
		t2.start();
		t3.start();

	}
}

运行的可能结果:
窗口A卖出票号:10
窗口A卖出票号:9
窗口A卖出票号:8
窗口C卖出票号:7
窗口C卖出票号:6
窗口C卖出票号:5
窗口B卖出票号:4
窗口B卖出票号:3
窗口A卖出票号:2
窗口A卖出票号:1

synchronized 与 Lock 的对比

相同:二者都可以解决线程安全问题
不同:1.synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器
Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())
2. Lock只有代码块锁,synchronized有代码块锁和方法锁
3.使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有 更好的扩展性(提供更多的子类)

实例

银行有一个账户。 有夫妻两个人分别向同一个账户存3000元,每次存1000,存3次。每次存完打 印账户余额。
实例1:继承Thread类同步方法方式

package com.qwy15;
class Account{
	private double balance;
	public Account() {
		// TODO Auto-generated constructor stub
	}
	public Account(double balance) {
		this.balance = balance;
	}
	public synchronized void deposit(double momey){
		if(momey>0){
			 try {
	                Thread.sleep(10);
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
			balance+=momey;
			System.out.println(Thread.currentThread().getName()+":存钱成功,余额:"+balance);
		}
	}
	
}

class Customer extends Thread{
	private Account accout;
	public Customer(Account accout) {
		super();
		this.accout = accout;
	}

	@Override
	public void run() {
		for(int i=0;i<3;i++){
			accout.deposit(1000);
		}
		
	}
	
}
public class AccountTest {
	public static void main(String[] args) {
		Account accout= new Account(0);
		Customer c1= new Customer(accout);
		Customer c2= new Customer(accout);
		
		
		c1.setName("丈夫");
		c2.setName("妻子");
		c1.start();
		c2.start();
	}
}


可能运行结果:
丈夫:存钱成功,余额:1000.0
妻子:存钱成功,余额:2000.0
妻子:存钱成功,余额:3000.0
妻子:存钱成功,余额:4000.0
丈夫:存钱成功,余额:5000.0
丈夫:存钱成功,余额:6000.0

实例2: 使用Lock方式

package com.qwy16;

import java.util.concurrent.locks.ReentrantLock;

class Account{
	private double balance;
	private ReentrantLock lock= new ReentrantLock();
	public Account() {
		// TODO Auto-generated constructor stub
	}
	public Account(double balance) {
		this.balance = balance;
	}
	public  void deposit(double momey){
		try {
			lock.lock();
			if(momey>0){
				 try {
		                Thread.sleep(10);
		            } catch (InterruptedException e) {
		                e.printStackTrace();
		            }
				balance+=momey;
				System.out.println(Thread.currentThread().getName()+":存钱成功,余额:"+balance);
			}
		} finally {
			lock.unlock();
		}
	}
	
}

class Customer extends Thread{
	private Account accout;
	public Customer(Account accout) {
		super();
		this.accout = accout;
	}

	@Override
	public void run() {
		for(int i=0;i<3;i++){
			accout.deposit(1000);
		}
		
	}
	
}
public class AccountTest {
	public static void main(String[] args) {
		Account accout= new Account(0);
		Customer c1= new Customer(accout);
		Customer c2= new Customer(accout);
		c1.setName("丈夫");
		c2.setName("妻子");
		c1.start();
		c2.start();
	}
}

可能的运行结果;
妻子:存钱成功,余额:1000.0
妻子:存钱成功,余额:2000.0
丈夫:存钱成功,余额:3000.0
丈夫:存钱成功,余额:4000.0
丈夫:存钱成功,余额:5000.0
妻子:存钱成功,余额:6000.0

未完待续
=============================================================================================
如有不妥之处,欢迎大家给予批评指出,如果对您有帮助,给留下个小赞赞哦
==============================================================================================

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值