多线程可能存在多个线程同时操作统一资源这样的线程不安全情况,解决这个问题就需要用到同步锁;同步锁需要用在多线程操作的资源之上分为几种情况
一、当需要加锁的是静态的时候
单例模式->懒汉式,线程不安全的
编程不安全:当多个线程同时操作同一份资源的时候,才有可能出现线程不安全问题
同步锁: synchronized
同步方法:使用在方法上(静态成员都可以)
简单,但是范围大,可能效率低
同步块:同步一段代码
复杂,锁有的代码的范围,锁什么锁的条件–>this,类,资源(自定义的引用数据类型的成员属性),根据具体的业务逻辑分析优缺点
锁要锁不变的东西,会变的内容锁不住
锁的代码范围太小了锁不住,太大了效率低
/*
* 同步方法(成员方法):
* 锁的代码范围太大,效率较低
*/
public class Web12306_02 implements Runnable{
int tickets=100;
/*
* 买票
*/
// A B C
@Override
public void run() {
while(true){
if(!test()){
break;
}
}
}
public synchronized boolean test(){
//A B C
if(tickets<=0){
return false;
}
try {
Thread.sleep(100); //ms数
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在购买第"+tickets--);
return true;
}
public static void main(String[] args) {
Web12306_02 web=new Web12306_02();
Thread t1=new Thread(web,"A");
Thread t2=new Thread(web,"B");
Thread t3=new Thread(web,"C");
t1.start();
t2.start();
t3.start();
}
}
/*
* 锁块:条件是类的class对象
* 锁了类,相当于把类的所有对象都锁住了,效率较低
*/
public class Web12306_04 implements Runnable{
int tickets=100;
/*
* 买票
*/
@Override
public void run() {
while(true){
//A B C
synchronized (Web12306_04.class) {
if(tickets<=0){
break;
}
try {
Thread.sleep(100); //ms数
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在购买第"+tickets--);
}
}
}
public static void main(String[] args) {
Web12306_04 web=new Web12306_04();
Thread t1=new Thread(web,"A");
Thread t2=new Thread(web,"B");
Thread t3=new Thread(web,"C");
t1.start();
t2.start();
t3.start();
}
}
/*
* 锁块:条件是资源,成员属性
* 锁要锁不变的东西,自定义的引用数据类型的对象永远不变
*/
public class Web12306_05 implements Runnable{
Tickets ticket = new Tickets();
/*
* 买票
*/
@Override
public void run() {
while(true){
//A B C
synchronized (ticket) { //锁的资源是自定义的对象地址,地址永远不变,使用前已经存在
if(ticket.num<=0){
break;
}
try {
Thread.sleep(100); //ms数
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在购买第"+ticket.num--);
}
}
}
public static void main(String[] args) {
Web12306_05 web=new Web12306_05();
Thread t1=new Thread(web,"A");
Thread t2=new Thread(web,"B");
Thread t3=new Thread(web,"C");
t1.start();
t2.start();
t3.start();
}
}
class Tickets{
int num=100;
}