线程安全的问题出现的原因
1.存在两个或者两个以上的线程
2.共享着同一个资源并且执行语句是多句
** 解决方法 **
第一种 (同步块代码)
1.格式
synchronized (锁对象){
执行的语句
}
2.锁对象可以是任意的对象 (必须是唯一的)
3.锁对象必须是共享的数据,不能为静态的成员变量
4.static或者常量池中属性
第二种(同步函数)
1.非静态的同步方法锁对象是----this对象(当前的对象)
2.静态的同步方法的锁对象是----当前类的claas文件 ===>(new Class)
(当类的class文件加载进入到内存的时候,jvm会自动的生成对应的(Class)描述文件)
** 同步函数代码**
//非静态的同步函数 ===>锁对象===> this对象
@Override
public synchronized void run() {
System.out.println("非静态同步函数的实现");
}
//静态同步函数 ===> 锁对象===> 当前方法所属类的class文件对象
public synchronized static void saleTitck(){
System.out.println("静态同步函数的实现");
}
同步代码块和同步函数的区别
1.同步代码块的锁对象我们自己指定,同步函数是对象指定
2.同步代码块可以随意指定那个范围被同步,同步函数必须是整个函数
3.如果没有存在线程安全的问题就不需要使用同步代码块
4.推荐使用同步代码块的使用
卖票的列子 (继承了Thread类)
/*
卖票的例子:
3个窗口同时买票的功能 同时卖50张票的功能
出现了线程安全的问题:
1.数据一定使用共享的数据使用static修饰
2.同步代码块的锁对象也是静态的 static 或者常量池中的常量
*/
public class SaleTitick extends Thread {
public SaleTitick(String name){
super(name);
}
//共50张 这个要共享数据 定义为static
static int titick = 50;
//这个锁对象一定钥匙静态的,才可以统一的管理
static Object o = new Object();
@Override
public void run() {
while (true){
//同步的代码块的方式 锁对象是任何的对象,任何对象都内置了隐式的一个状态 这个状态就是记录锁的状态了
synchronized ("锁"){
if (titick>0){
System.out.println(Thread.currentThread().getName()+"卖出第"+titick+"张票");
titick--;
}else{
System.out.println("票卖完了");
break;
}
}
}
}
public static void main(String[] args) {
SaleTitick saleTitick1 = new SaleTitick("窗口1");
SaleTitick saleTitick2 = new SaleTitick("窗口2");
SaleTitick saleTitick3 = new SaleTitick("窗口3");
//调用start方法
saleTitick1.start();
saleTitick2.start();
saleTitick3.start();
}
}
卖票列子(实现 Runable接口)
/**
需求:
卖50张票的实现了Runable类
*/
public class SaleTitckRunable implements Runnable {
static int titck = 50; //静态数据共享
static Object o = new Object(); //锁对象共享
@Override
public void run() {
while (true){
//同步代码块的方法去实现这个功能
synchronized (o){
if (titck>0){
System.out.println(Thread.currentThread().getName()+":"+titck);
titck--;
}else{
System.out.println("卖完了");
break;
}
}
}
}
public static void main(String[] args) {
SaleTitckRunable runable = new SaleTitckRunable();
SaleTitckRunable runable1 = new SaleTitckRunable();
SaleTitckRunable runable2 = new SaleTitckRunable();
Thread thread = new Thread(runable,"线程1");
Thread thread1 = new Thread(runable1 ,"线程2");
Thread thread2 = new Thread(runable2,"线程3");
thread.start();
thread1.start();
thread2.start();
}
}
死锁出现的现象 (两个线程都互相同步,你不让我我也不让你)
** 代码如下**
/**
死锁出现的问题:
需求:
天气热,去办公室拿遥控和电池
zhangsan先去拿遥控器,再去拿电池
lisi先去拿电池,然后再去拿遥控器
*/
public class DeadLock extends Thread{
public DeadLock(String name){
super(name);
}
//重写run方法
@Override
public void run() {
while (true){
if ("zhangsan".equals(this.getName())){
synchronized ("遥控器"){
System.out.println(this.getName()+"拿到了遥控器,接下来去拿电池");
}
synchronized ("电池"){
System.out.println(this.getName()+"拿到了电池真开心");
}
}else if ("lisi".equals(this.getName())){
synchronized ("电池"){
System.out.println(this.getName()+"拿到了电池,接下来去拿遥控器");
}
synchronized ("遥控器"){
System.out.println(this.getName()+"拿到了遥控器真开心");
}
}
}
}
public static void main(String[] args) {
DeadLock deadLock = new DeadLock("zhangsan");
DeadLock deadLock1 = new DeadLock("lisi");
deadLock.start();
deadLock1.start();
}
}