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~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~pia!