Java基础笔记34-synchronized(同步锁)关键字与Lock锁

Java基础笔记34-synchronized(同步锁)关键字与Lock锁

1. synchronized 关键字

  • 使用 synchronized 关键字 线程同步
    • 关键词:synchronize 同步锁
    • 语法:synchronize(锁){锁的内容}
    • 要求:多个线程在操作时所用的锁是同一把锁

代码示例:

public class ThreadMethod1 {
	public static void main(String[] args) {
//		Ticket tic = new Ticket();
//		//两个进程使用同一个对象
//		Thread th1 = new Thread(tic,"窗口一");
//		Thread th2 = new Thread(tic,"窗口二加急");
//		th1.start();
//		th2.start();
		Object obj = new Object();
		Ticket2 tic1 = new Ticket2(obj);
		tic1.setName("窗口一");
		tic1.start();
		Ticket2 tic2 = new Ticket2(obj);
		tic2.start();
	}
}

/**
 * 卖票,使用实现接口,
 */
class Ticket implements Runnable{
	int tickets = 50;
	@Override
	public void run() {
		
//		while(tickets>0) {
//			System.out.println(Thread.currentThread().getName() + "剩余票数:" + (--tickets));
//		}
		//使用循环,进程循环进入
		while(true) {
			//同步锁,保证同时只能有一个进程执行循环体,以共同的唯一资源作为唯一锁,
			synchronized(Ticket.class) {
				//代码块执行条件
				if(tickets>0) {
					try {
						//sleep()方法暂停当前进程,以免一个进程执行过快
						Thread.sleep(20);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "剩余票数:" + (--tickets));
				}else {
					break;
				}
			}	
		}
	}
}

/**
 * 使用继承,
 *
 */
class Ticket2 extends Thread{
	//创建唯一锁
	private Object obj;
	private static int tickets = 100;		
	public Ticket2() {}	
	public Ticket2(Object obj) {
		this.obj = obj;
	}
	@Override
	public void run() {
		while(true) {
			synchronized(obj) {
				if(tickets>0) {
					try {
						Thread.sleep(20);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "剩余票数:" + (--tickets));
				}else {
					break;
				}
			}
		}
	}
}

2.Lock锁

  • 使用 ReentrantLock 实现同步
    • lock() 方法:上锁
    • unlock() 方法:释放锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {
	public static void main(String[] args) {
		//创建锁对象
		Lock lock = new ReentrantLock();
		//创建要执行的任务
		Ticket tic = new Ticket(lock);
		//创建线程
		Thread t1 = new Thread(tic,"窗口一");
		Thread t2 = new Thread(tic);
		//开启线程
		t1.start();
		t2.start();
	}
}
class Ticket implements Runnable{

	private int tickets = 100;	
	private Lock lock;	
	public Ticket(Lock lock) {
		this.lock = lock;
	}
	@Override
	public void run() {
		while(true) {
			//加锁
			lock.lock();
			if(tickets>0) {
				try {
					Thread.sleep(50);
					System.out.println(Thread.currentThread().getName() + "剩余:" +(--tickets));
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally {
					//释放锁
					lock.unlock();
				}
				
			}else {
				//lock.unlock();
				break;
			}		
		}
	}	
}

3.synchronized和Lock锁的区别

1、synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁

2、用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了

3、synchronized放弃锁只有两种情况:①线程执行完了同步代码块的内容②发生异常;而lock不同,它可以设定超时时间,也就是说他可以在获取锁时便设定超时时间,如果在你设定的时间内它还没有获取到锁,那么它会放弃获取锁然后响应放弃操作


版权声明:本文为w1226234212原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。