25.多线程同步

1.同步代码块

语法

synchronized(锁) {
		//需要访问临界资源的代码段
	}

锁必须是一个对象

  • 1)程序走到代码段中,就用锁来锁住了临界资源,这个时候,其他线程不能执行代码段中的代码,只能在锁外边等待
  • 2)执行完代码段中的这段代码,会自动解锁。然后剩下的其他线程开始争抢cpu时间片
  • 3)一定要保证不同的线程看到的是同一把锁,否则同步代码块没有意义

例子:

package cn.cc.day22;

/**
 * @author CC
 * 线程同步代码块
 */
public class Ticket {

	public static void main(String[] args) {
		//只能new一个对象
		TicketThread ticketThread = new TicketThread();
		Thread td3 = new Thread(ticketThread);
		td3.setName("线程3");
		Thread td1 = new Thread(ticketThread);
		td1.setName("线程1");
		Thread td2 = new Thread(ticketThread);
		td2.setName("线程2");
		
		td1.start();
		td2.start();
		td3.start();
	}

}

class TicketThread implements Runnable{
	//总票数
	private int ticket = 5;
	public void run() {
		for (int i = 0; i < 100	; i++) {
			//使用线程同步:同步代码块
			//同步代码块中的代码,不允许多个线程同时执行
			//任何对象都能作为同步的标记
			//用this代表锁,只能创建一个当前类的对象
			synchronized (this) {
				//分析:this代表TicketThread的对象
				//如果有线程访问同步代码块中的代码,将this设为1
				//又有线程进行访问同步代码块中的代码时,会判断是否是同一个this,如果是同一个this,判断是否是1
				//如果是1,则此线程处于阻塞状态,不允许执行同步代码块中的代码
				//当第一个线程结束同步代码块中的代码执行后,将this设置为0,表示处于阻塞状态的线程进入到就绪状态
				//要同步的代码
				if (ticket>0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+":"
					+"卖出第"+ticket+"张票,还剩"+--ticket+"张票");
				}
			}
		}
	}
	
}

对象锁的分析:

  • this代表当前类的对象
  • 如果有线程访问同步代码块中的代码,将this设为1,又有线程进行访问同步代码块中的代码时,会判断是否是同一个this,如果是同一个this,判断是否是1.如果是1,则此线程处于阻塞状态,不允许执行同步代码块中的代码
  • 当第一个线程结束同步代码块中的代码执行后,将this设置为0,表示处于阻塞状态的线程进入到就绪状态

2.线程同步方法

package cn.cc.day22;

/**
 * @author CC
 * 线程同步方法
 */
public class Ticket2 {

	public static void main(String[] args) {
		TicketThread2 t = new TicketThread2();
		Thread td1 = new Thread(t);
		Thread td2 = new Thread(t);
		Thread td3 = new Thread(t);
		td1.start();
		td2.start();
		td3.start();
	}
}

class TicketThread2 implements Runnable{
	private int ticket = 5;
	@Override
	public synchronized void run() {
		for (int i = 0; i < 100; i++) {
			if (ticket > 0) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":"
						+"卖出第"+ticket+"张票,还剩"+--ticket+"张票");
			}
		}
	}
}

在这里插入图片描述


3.同步锁:

package cn.cc.day22;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @author CC
 * 同步锁
 */
public class Ticket3 {

	public static void main(String[] args) {
		LockThread lt = new LockThread();
		Thread td1 = new Thread(lt);
		Thread td2 = new Thread(lt);
		Thread td3 = new Thread(lt);
		td1.start();
		td2.start();
		td3.start();
	}
}

class LockThread implements Runnable{
	private int ticket = 5;
	//声明锁对象
	ReentrantLock myLock = new ReentrantLock();
	
	@Override
	public void run() {
		myLock.lock();//上锁
		for (int i = 0; i < 100; i++) {
			if (ticket>0) {
				try {
					Thread.sleep(100);//休眠过程中锁依然有效,抱着锁休眠
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":"
						+"卖出第"+ticket+"张票,还剩"+--ticket+"张票");
			}
		}
		myLock.unlock();//解锁
	}
}

4.死锁

package cn.cc.day22;

/**
 * @author CC
 * 死锁
 */
public class DeadLock {

	public static void main(String[] args) {
		DeadLock d = new DeadLock();
		Thread td1 = new DeadThread();
		Thread td2 = new DeadThread();
		td1.start();
		td2.start();
	}
}

class DeadThread extends Thread{
	//声明两个对象,作为锁住的对象
	static Object o1 = new Object();
	static Object o2 = new Object();
	//锁住的标记
	static boolean flag = true;
	public void run() {
		if (flag) {
			//锁住O1
			synchronized (o1) {
				System.out.println(Thread.currentThread().getName()+"获取了第一个对象o1,"
						+ "等待第二个锁对象o2");
				flag = !flag;
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				synchronized (o2) {
					System.out.println(Thread.currentThread().getName()+"获取了锁对象o1和o2,"
							+ "释放两个对象");
				}
			}
		}else {
			//锁住o2
			synchronized (o2) {
				System.out.println(Thread.currentThread().getName()+"获取了第一个对象o2,"
						+ "等待第二个锁对象o1");
				flag = !flag;
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				synchronized (o1) {
					System.out.println(Thread.currentThread().getName()+"获取了锁对象o1和o2,"
							+ "释放两个对象");
				}
			}
		}
	}
}

Biu~~~~~~~~~~~~~~~~~~~~????′éaé???è?¨??|é???gif??è?¨????è?????~~~~~~~~~~~~~~~~~~~~~~pia!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值