多线程的安全问题
前提
多线程同时操作同一份资源时会出先数据不安全问题
买票问题简介,有张三和李四两个人买100张票
public class DemoTickets implements Runnable{
static int tickets = 100;
public static void main(String[] args) {
DemoTickets demoTickets = new DemoTickets();
Thread th1 = new Thread(demoTickets,"张三");
Thread th2 = new Thread(demoTickets,"李四");
th1.start();
th2.start();
}
@Override
public void run() {
while (true){
if (tickets<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"买了第"+(tickets--)+"票");
}
}
}
如图和代码所示数据就不安全了可能会出先先卖第100张票再买99张的情况,因此需要同步锁
锁方法
public synchronized void run() {
while (true) {
if (tickets <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "买了第" + (tickets--) + "票");
}
}
只需要在方法上添加 synchronized 关键字就可以在此方法上施加同步锁那么进入此方法就需要排队进入,即一个一个进,就不会出现数据不安全问题,但是效率会低
锁块
即将方法中关键代码进行锁住
锁块分为3中,1.锁类 2. 锁对象3.锁资源
锁类
public void run() {
synchronized (DemoTickets02.class) {
while (true) {
if (tickets <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "买了第" + (tickets--) + "票");
}
}
}
此方法锁的是DemoTickets02的这个类即这个类所属的所有对象都会被锁住
锁对象
public void run() {
synchronized (this) {
while (true) {
if (tickets <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "买了第" + (tickets--) + "票");
}
}
}
上述锁的是对象,锁的这个线程所属的对象,即这个对象的所有资源都会被锁住
锁资源
public void run() {
synchronized (Tickets.class) {
while (true) {
if (tickets <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "买了第" + (tickets--) + "票");
}
}
}
}
class Tickets{
static int tickets = 100;
}
创建一个类里面包含着要锁住的资源即可
注意事项
如果同步的范围太大那么效率太低,如果锁的范围太小那么有可能锁不住导致数据不安全