javaseday12(线程同步代码块 函数线程安全死锁)
javaseday12(线程,同步代码块 函数,线程安全,死锁)
sleep(time)必须指定睡眠时间 单位是毫秒到点自动唤醒
CPU的执行资格:可以被cpu处理 在处理队列中排队
CPU的执行权:正在被CPU处理
一个特殊的状态 :就绪(临时阻塞) 具备了执行的资格但是还没有获取资源(执行权)
创建线程的第一种方式:继承Thread类 cpu快速切换 导致线程切换
Thread 中有封装线程任务的方法
将自己的方法放在子类的run()中
创建线程的第二种方式:实现Runnable接口
1、定义类实现Runnable接口
2、覆盖接口中的run方法 将线程的任务代码封装到run方法中
3、通过Thread类创建线程对象,并将Runnable接口的子类对象作为构造函数的参数进行传递
因为线程的任务都封装在Runnable接口子类对象的run方法中 所以要在线程对象创建时就必须明确要运行的任务
4、调用线程对象的start方法开启线程
实现Runnable 接口的好处(区别):
1、将线程的任务从线程的子类中分离出来,进行了单独的封装
按照面向对象的思想将任务封装成对象
2、避免了java单继承的局限性
所以创建线程的第二种方式较为常见
子类已经继承了一个fu 可以用接口来扩展功能 让其中的内容作为线程的任务执行
因为不是Thread的儿子
所以要通过
Demo d = new Demo();
Thread t1 = new Thread (d);
Thread(Runnable target)
分配一个新的 Thread对象
简化:
class Thread{
private Runnable r;
Thread(){}
Thread(Runnable r){
this.r=r;
}
public void run(){ //继承的时候该方法被 覆盖 接口的时候通过构造函数 传进去r 然后通过start 调用该方法
if(r!=null)
r.run();
}
public void start(){
run();
}
}
Runnable仅仅是将线程的任务进行了对象的封装 而不需要继承Thread
Thread 的 run 也来自Runnable 不过做了一个默认的实现
用静态限制具有局限性 (有2个100张票要卖)
1个线程不能启动多次 算是在主线程异常 在主函数内的是主线程异常 run里面的才是其他线程异常
Ticket t = new Ticket(); //创建一个线程任务对象 通过Runnable接口
Thread t = new Thread(t);
Thread t1 = new Thread(t);
Thread t2= new Thread(t);
Thread t3= new Thread(t);
t.start();
t1.start();
t2.start();
t3.start();
线程安全问题产生的原因:
1、多个线程在操作共享的数据
2、操作共享数据的线程代码有多条
当一个线程在执行操作共享数据的多条代码过程中 其他线程参与了运算
就会导致线程安全问题的产生
解决思路
就是将多条操作共享数据的线程代码封装起来 当有线程在执行这些代码的时候
其他线程不可以参与运算 必须要当前线程把这些代码都执行完毕后 其他线程才能参与运算
在java中用同步代码块来解决这个问题
同步代码块的格式
synchronized(对象){ 不是真实存在实际叫锁(初始为1 线程进来看到1后进来改为0 出去改为1)
需要被同步的代码;
}
同步的好处:解决线程安全的问题
同步的弊端: 相对降低效率 因为执行权会不断切换 有无效判断(因为同步外的线程都会判断同步锁)
同步的前提: 同步中必须有多个线程并使用同一个锁 注意同一个锁
在函数上加上修饰符 synchronizd 同步函数
public void run(){
while(true){
show();
}
}
public synchronized void show(){
if(){}
}
同步函数 的锁是this 通过同步代码块 和同步函数 然后 flag = true 执行 同步函数 flag = flase 执行同步代码块来验证
同步函数和同步代码块的区别
同步函数的锁是固定的this
同步代码块的锁是任意的对象
建议使用同步代码块 同步函数是同步代码块的简写 虽然简化 但是唯一锁
静态的函数 的锁是this.getClass()字节码对象 也可以用类名.class
多线程下的单例
饿汉式 先创建 对象
懒汉式 有需求再创建 有线程安全问题 可以在函数加synchronized 但是降低 了效率 所以在代码块加synchronized(Single.class)
不能加getclass() 因为getclass 是非静态的
public static Singele getInstance(){
if(s==null){ //解决效率问题
synchronized(Single.class){
if(s==null)//解决线程安全问题
s= new Single();
}
}
return s;
}
死锁:常见情景之一:同步嵌套
Test implements Runnable
private boolean flag;
Test(boolean flag){
this.flag = flag;
}
public void run(){
if(flag){
while(true){
synchronized(MyLock.locka){
syso
synchronized(Mylock.lockb){
syso
}
}
}
}
else{
while(true){
synchronized(MyLock.locka){
syso
synchronized(Mylock.lockb){
syso
}
}
}
}
}
class MyLock{
public static final Object locka = new Object();
public staticfinal Object lockb= newObject();
}
//构造函数和构造代码块的死锁
public static void main(String[] args) {
Demo r = new Demo();
Thread t = new Thread(r);
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Thread t3 = new Thread(r);
t.start();
t1.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
r.flag = false;
t2.start();
t3.start();
}
}
class Demo implements Runnable{
private int num = 100;
boolean flag = true;
Object obj = new Object();
public void run() {
if (flag) {
while (true) {
synchronized (obj) {
show();
}
}
} else
while (true) {
this.show();
}
}
public synchronized void show() {
synchronized (obj) { //卡在这 一个this 一个 obj
if (num > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "..." + num--);
}
}
}
}
简单点的死锁
public static void main(String[] args) {
Demo r = new Demo(true);
Demo r1 = new Demo(false);
Thread t = new Thread(r);
Thread t1 = new Thread(r1);
t.start();
t1.start();
}
}
class Demo implements Runnable{
boolean flag = true;
Demo(boolean flag){
this.flag = flag;
}
public void run() {
if(flag) {
while(true) {
synchronized (MyLock.locka) {
System.out.println(Thread.currentThread().getName()+"if locka");
synchronized(MyLock.lockb) {
System.out.println(Thread.currentThread().getName()+"if lock b");
}
}
}
}
else {
while(true) {
synchronized (MyLock.lockb) {
System.out.println(Thread.currentThread().getName()+" else lockb");
synchronized(MyLock.locka) {
System.out.println(Thread.currentThread().getName()+" else locka");
}
}
}
}
}
}
class MyLock {
public static final Object locka = new Object();
public static final Object lockb = new Object();
}
javaseday12(线程同步代码块 函数线程安全死锁)相关教程