java线程同步的死锁_javaseday12(线程同步代码块 函数线程安全死锁)

javaseday12(线程同步代码块 函数线程安全死锁)

javaseday12(线程,同步代码块 函数,线程安全,死锁)

f78b483d13de3b5f506d76c54cabe857.png

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(线程同步代码块 函数线程安全死锁)相关教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值