java多线程方法锁_荐 Java中多线程的使用(超级超级详细)线程安全+线程锁原理解析...

Java中多线程的使用(超级超级详细)线程安全+保证线程安全的三种方式 (同步代码块+同步方法+lock锁) 5

当我们使用多线程访问同一个资源时,且多个线程对资源有写的 操作就容易出现线程安全问题,java为了解决线程安全问题引入了同步机制来解决,即在一个线程使用公共代码块的时候另一个线程不可以使用

下面我用一个抢票的案例来给大家讲解保证线程安全的几种方式

首先我们先来看看没有使用锁的情况下出现的情况

package ThreadSafe;

public class ThreadSafe implements Runnable {

//定义一个多线程共享的 票源

private int ticketsum=100;

//设置买票的线程任务

public void run(){

while(true) {

//判断还有没有票

if (ticketsum > 0) {

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

String name = Thread.currentThread().getName();

System.out.println(name + "正在卖:" + ticketsum);

ticketsum--;

}

}

}

}

package ThreadSafe;

public class Main {

public static void main(String[] args) {

//创建Runable实现对象

ThreadSafe threadSafe = new ThreadSafe();

//创建Thread类对象

Thread one = new Thread(threadSafe, "一号");

Thread two = new Thread(threadSafe, "二号");

Thread three = new Thread(threadSafe, "三号");

one.start();

two.start();

three.start();

}

}

出现的问题

出现负数的票与重复票

7acade18f6547970c2467d59d0450a05.png

对于线程安全原理不懂的兄弟可以去看看我的另一篇文章

链接:https://blog.csdn.net/pjh88/article/details/107359745

下面演示加锁的情况

方法一:同步代码块

同步代码块:synchronized关键字可以用于某个区块中,表示对这个区块的资源实行互斥访问

synchronized(同步锁){

需要同步操作的代码

}

同步锁:

对象的同步锁只是一个概念,可以想象为在改对象上上了一把锁

1.锁可以是任意的类型

2.多个线程对象要使用同一把锁

任何时候都最多允许一个对象拥有同步锁谁拿到锁就谁进入同步代码块

使用以下代码块来演示

package ThreadSafe;

public class Main {

public static void main(String[] args) {

//创建Runable实现对象

ThreadSafe threadSafe = new ThreadSafe();

//创建Thread类对象

Thread one = new Thread(threadSafe, "一号");

Thread two = new Thread(threadSafe, "二号");

Thread three = new Thread(threadSafe, "三号");

one.start();

two.start();

three.start();

}

}

package ThreadSafe;

public class ThreadSafe implements Runnable {

//定义一个多线程共享的 票源

private int ticketsum=100;

java.lang.Object object=new java.lang.Object();

//设置买票的线程任务

public void run(){

while(true) {

synchronized (object){

//判断还有没有票

if (ticketsum > 0) {

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

String name = Thread.currentThread().getName();

System.out.println(name + "正在卖:" + ticketsum);

ticketsum--;

}

}

}

}

}

结果

可以发现没有线程不安全的情况出现

d35e34ef5c418e21b200c0d477667d0e.png

同步代码块原理解析:

ca82b3595ed706cf717ccdc8df08ea3a.png

同步方法

什么是同步方法?

使用synchronized修饰的方法叫做同步方法,保证线程安全,当a线程执行该方法的时候,其他线程只可以在方法外等待

public synchornized void method(){

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

}

那么锁对象在哪呢?

锁对象是隐藏的,谁调用这个方法谁就是隐藏的锁对象,

对于非static方法锁对象就是this

对于static方法锁对象是类名.class

上代码

package ThreadSafe;

public class ThreadSafe implements Runnable {

//定义一个多线程共享的 票源

private int ticketsum=100;

java.lang.Object object=new java.lang.Object();

//设置买票的线程任务

public void run(){

while(true) {

shuchu();

}

}

public synchronized void shuchu(){

//判断还有没有票

if (ticketsum > 0) {

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

String name = Thread.currentThread().getName();

System.out.println(name + "正在卖:" + ticketsum);

ticketsum--;

}

}

}

package ThreadSafe;

public class Main {

public static void main(String[] args) {

//创建Runable实现对象

ThreadSafe threadSafe = new ThreadSafe();

//创建Thread类对象

Thread one = new Thread(threadSafe, "一号");

Thread two = new Thread(threadSafe, "二号");

Thread three = new Thread(threadSafe, "三号");

one.start();

two.start();

three.start();

}

}

结果

由结果可以看出没有出现线程安全的问题

c7f12f0d324eb0fbcbedd95d6bfc32b1.png

另一种实现方法

上代码

package ThreadSafe;

public class ThreadSafe implements Runnable {

//定义一个多线程共享的 票源

private int ticketsum=100;

java.lang.Object object=new java.lang.Object();

//设置买票的线程任务

public void run(){

while(true) {

shuchu();

}

}

public void shuchu(){

synchronized(this) {

//判断还有没有票

if (ticketsum > 0) {

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

String name = Thread.currentThread().getName();

System.out.println(name + "正在卖:" + ticketsum);

ticketsum--;

}

}

}

}

package ThreadSafe;

public class Main {

public static void main(String[] args) {

//创建Runable实现对象

ThreadSafe threadSafe = new ThreadSafe();

//创建Thread类对象

Thread one = new Thread(threadSafe, "一号");

Thread two = new Thread(threadSafe, "二号");

Thread three = new Thread(threadSafe, "三号");

one.start();

two.start();

three.start();

}

}

所得的结果和上面是一样的

Lock锁

java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作, 同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。

Lock锁的功能

public void lock()加同步锁

public void unlock() 释放同步锁

下面使用一段代码演示

package ThreadSafe;

public class Main {

public static void main(String[] args) {

//创建Runable实现对象

ThreadSafe threadSafe = new ThreadSafe();

//创建Thread类对象

Thread one = new Thread(threadSafe, "一号");

Thread two = new Thread(threadSafe, "二号");

Thread three = new Thread(threadSafe, "三号");

one.start();

two.start();

three.start();

}

}

package ThreadSafe;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class ThreadSafe implements Runnable {

//定义一个多线程共享的 票源

private int ticketsum=100;

ReentrantLock lock=new ReentrantLock();

//设置买票的线程任务

public void run(){

while(true) {

shuchu();

}

}

public void shuchu(){

while (true){

lock.lock();

//判断还有没有票

if (ticketsum > 0) {

try {

Thread.sleep(10);

String name = Thread.currentThread().getName();

System.out.println(name + "正在卖:" + ticketsum);

ticketsum--;

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

lock.unlock();

}

}

}

}

}

以上就是java锁的一些基本知识,如有错误还请各位批评指正,喜欢我的文章的可以关注我,也可以点赞收藏支持一下

37c6f91da4b020164a39936ae3c5362e.png

本文地址:https://blog.csdn.net/pjh88/article/details/107366533

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值