Java教程

Java中多线程安全、同步、死锁,38岁的中年失业者怎么活下去

本文主要是介绍Java中多线程安全、同步、死锁,38岁的中年失业者怎么活下去,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

{

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + T–);

}

}

}

}

}

对上述代码进行改进,增加了同步代码块,即同步锁,当线程进入同步代码块的时候,会判断有没有同步锁,如果有,则获取同步锁,进入同步中,去执行代码块,执行完毕后,出去了同步代码块,线程就将锁还回去,如果判断没有锁,就被阻挡在同步代码块外面不能执行,只能等待,这样,线程安全问题就解决了,但导致程序运行的速度下降了。总:没有锁的线程不能进入同步,在同步中的线程,不出去同步,就不会释放锁。

2、同步方法


(1) 普通方法同步

格式:在方法声明上加上 synchronized

_public synchronized void method() {

可能会产生线程安全问题的代码

}_

注:同步方法中的锁对象是 this

再对售票的案例进行改进:

public class Ticket implem

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

ents Runnable{

int T = 10;

//定义锁对象

Object lock = new Object();

@Override

public void run() {

while (true)

{

//同步方法

method();

}

}

private synchronized void method()

{

if(T > 0)

{

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + T–);

}

}

}

同步方法也能解决线程安全问题

(2) 静态同步方法

格式:在方法声明上加上 static synchronized

_public static synchronized void method(){

可能会产生线程安全的代码

}_

注:静态同步方法中的锁对象是 类名.class

三、死锁

====

在使用同步锁的时候,存在弊端:当线程任务中出现多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发程序的无限等到,这种现象称为死锁。

格式:

_synchronized(A锁){

synchronized(B锁){

}

}_

四、Lock 接口

=========

Lock 接口实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作,Lock 接口中常用方法如下:

  • void lock():获得锁

  • void unlock():释放锁

使用 Lock 接口继续对售票案例进行修改:

public class Ticket implements Runnable{

int T = 10;

//创建Lock对象

Lock ck = new ReentrantLock();

@Override

public void run() {

while (true)

{

//调用lock方法获取锁

ck.lock();

if(T > 0)

{

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + T–);

}

//释放锁

ck.unlock();

}

}

}

五、等待和唤醒机制

=========

等待唤醒机制是为了方便处理进程之间通信的手段,多个线程在处理同一个资源时,由于处理的动作(线程的任务)不行同,为了使各个线程能够有效的利用资源,便采取了等待唤醒机制。等待唤醒机制涉及到的方法:

  • wait():等待。将正在执行的线程释放其执行资格和执行权,并存储到线程池中

  • notify():唤醒。唤醒线程池中被 wait() 的线程,一次唤醒一个,而且是任意的

  • notifyAll():唤醒全部。可以将线程池中的所有 wati() 线程都唤醒

注:

  • 这些方法都是在同步中才有效,在使用时必须注明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程

  • 因为这些方法在使用的时候要注明所属的锁,而锁又是任意对象,所以这些方法是定义在 Object 类中的

代码实例:

来看一个例子,现有Person类,存储了姓名和年龄,使用 inPut 线程对 Person 类输入信息,使用 outPut 线程对 Person 类获取打印信息

//模拟Person类

public class Person {

String name;

int age;

boolean flag = false;

}

//输入线程任务inPut类

public class inPut implements Runnable {

private Person p;

int count = 0;

public inPut(Person p) {

this.p = p;

}

public void run() {

while (true)

{

synchronized §

{

if(p.flag)

{

try {

p.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

if(count % 2 == 0)

{

p.name = “儿童”;

p.age = 3;

}

else

{

p.name = “老人”;

p.age = 99;

}

p.notify();

p.flag = true;

}

count++;

}

}

}

//输出线程任务outPut类

public class outPut implements Runnable {

private Person p;

public outPut(Person p)

{

this.p = p;

}

public void run() {

while (true)

{

synchronized §

{

if(!p.flag)

{

try {

p.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(p.name + “:” + p.age + “岁”);

p.notify();

p.flag = true;

}

}

}

}

//在主线程中调用

public static void main(String[] args)

{

Person P = new Person();

inPut in = new inPut§;

outPut out = new outPut§;

Thread T1 = new Thread(in);

Thread T2 = new Thread(out);

T1.start();

T2.start();

}
分析:

  • 输入 inPut 类:输入完成后,必须等待输出结果打印结束才能进行下一次赋值,赋值后,执行wait()方法永远等待,直到被唤醒,唤醒后重新对变量赋值,赋值后再唤醒输出线程 notify(),自己再wait()
  • 输出 outPut 类:输出完成后,必须等待输入的重新赋值后才能进行下一次输出,在输出等待前,唤醒输入的notify(),自己再 wait() 永远等待,直到被唤醒
这篇关于Java中多线程安全、同步、死锁,38岁的中年失业者怎么活下去的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!