Java 多线程(2) 线程同步 死锁
线程同步
指多个线程操作同一个资源,即并发
处理这种问题就需要用到线程同步机制,多个线程同时访问此对象会进入这个对象的等待队列,一个一个来。 同时为了保证安全,除了队列还要加上锁机制。

通过同步解决买票问题

//多个线程操作同一个对象
public class ThreadDemo3 implements Runnable{
private int tickNums=10;
boolean flag=true;
public void run() {
while(flag){
try{
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
buy();
}
}
private synchronized void buy() {//加上了synchronized关键字
if(tickNums<=0){
flag=false;
return;
}
System.out.println(Thread.currentThread().getName()+"拿到了第"+tickNums--+"票");
}
public static void main(String[] args) {
ThreadDemo3 threadDemo3=new ThreadDemo3();
new Thread(threadDemo3,"小明").start();
new Thread(threadDemo3,"小红").start();
new Thread(threadDemo3,"小蓝").start();
}
}
同步块

死锁

代码例子
public class DeadLockDemo {
public static void main(String[] args) {
UseItem useItem1=new UseItem(0,"小明");
UseItem useItem2=new UseItem(1,"小红");
useItem1.start();
useItem2.start();
}
}
class ItemA{}
class ItemB{}
class UseItem extends Thread{
static ItemA itemA=new ItemA();
static ItemB itemB=new ItemB();
//通过static保证只有一份
int num;//
String username;
UseItem(int num,String username){
this.num=num;
this.username=username;
}
private void useitem() throws InterruptedException {
if(num==0){//编号为0的人
synchronized (itemA){//使用A物品 即锁了A
System.out.println(this.username+"在使用物品A");
Thread.sleep(1000);//通过sleep 模拟用物品一秒
synchronized (itemB){
System.out.println(this.username+"在使用物品B");
}
}
}
else {
synchronized (itemB){
System.out.println(this.username+"在使用物品B");
Thread.sleep(2000);//通过sleep 模拟用物品两秒
synchronized (itemA){
System.out.println(this.username+"在使用物品A");
}
}
}
}
@Override
public void run() {
try {
useitem();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行上面代码就会出现死锁
解决方法
避免一个synchronized块里出现两种对象的锁
public class DeadLockDemo {
public static void main(String[] args) {
UseItem useItem1=new UseItem(0,"小明");
UseItem useItem2=new UseItem(1,"小红");
useItem1.start();
useItem2.start();
}
}
class ItemA{}
class ItemB{}
class UseItem extends Thread{
static ItemA itemA=new ItemA();
static ItemB itemB=new ItemB();
//通过static保证只有一份
int num;//
String username;
UseItem(int num,String username){
this.num=num;
this.username=username;
}
private void useitem() throws InterruptedException {
if(num==0){//编号为0的人
synchronized (itemA){//使用A物品 即锁了A
System.out.println(this.username+"在使用物品A");
Thread.sleep(1000);//通过sleep 模拟用物品一秒
}
synchronized (itemB){
System.out.println(this.username+"在使用物品B");
}
}
else {
synchronized (itemB){
System.out.println(this.username+"在使用物品B");
Thread.sleep(1000);//通过sleep 模拟用物品两秒
}
synchronized (itemA){
System.out.println(this.username+"在使用物品A");
}
}
}
@Override
public void run() {
try {
useitem();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
LOCK锁

通过lock锁解决买票问题
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
new Thread(buyTicket,"小明").start();
new Thread(buyTicket,"小红").start();
new Thread(buyTicket,"小绿").start();
}
}
class BuyTicket implements Runnable{
private int num=50;
private boolean flag=true;
//定义lock
private ReentrantLock lock=new ReentrantLock();
public void stop(boolean flag) {
this.flag =false;
}
private void buy(){
while(flag){
try{
Thread.sleep(1000);
lock.lock();//上锁
if(num<=0){
flag=false;
break ;
}
else {
System.out.println(Thread.currentThread().getName()+"买了第"+num--+"票");
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
lock.unlock();//解锁
}
}
}
@Override
public void run() {
buy();
}
}


浙公网安备 33010602011771号