java线程安全实现_java线程安全如何实现?有哪些实现方法?

你知道java的线程安全应该如何去实现吗?java线程安全的实现方式又有哪些呢?下面就和小编一起来看看具体的实现方法吧!

一个程序在运行起来的时候,会转换成进程,一般来说,会含有很多个线程。

一般的情况下,在一个进程当中,那些比较费时的操作,经常会采用多线程来进行解决。

例如:

生活当中经常可见的银行取钱、售票等,经常就会涉及到并发的问题,那么这个时候,往往就要用到多线程技术。

在进程当中,有多个并发线程进入一个重要数据的代码块的时候,在修改数据的过程当中,有很大的可能会引发线程安全的问题,从而引起了数据异常。

那么下面以售票问题作为例子,来演示线程安全的问题。

首先,在不对多线程数据进行保护的情况下会引发出来的状况public class ThreadUnSecurity {

static int tickets = 10;

class SellTickets implements Runnable{

@Override

public void run() {

// 未加同步时产生脏数据

while(tickets > 0) {

System.out.println(Thread.currentThread().getName()+"--->售出第:  "+tickets+" 票");

tickets--;

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

if (tickets <= 0) {

System.out.println(Thread.currentThread().getName()+"--->售票结束!");

}

}

}

public static void main(String[] args) {

SellTickets sell = new ThreadUnSecurity().new SellTickets();

Thread thread1 = new Thread(sell, "1号窗口");

Thread thread2 = new Thread(sell, "2号窗口");

Thread thread3 = new Thread(sell, "3号窗口");

Thread thread4 = new Thread(sell, "4号窗口");

thread1.start();

thread2.start();

thread3.start();

thread4.start();

}

}

上面的代码的运行结果:1号窗口--->售出第:  10 票

3号窗口--->售出第:  10 票

2号窗口--->售出第:  10 票

4号窗口--->售出第:  10 票

2号窗口--->售出第:  6 票

1号窗口--->售出第:  5 票

3号窗口--->售出第:  4 票

4号窗口--->售出第:  3 票

2号窗口--->售出第:  2 票

4号窗口--->售出第:  1 票

1号窗口--->售出第:  1 票

3号窗口--->售票结束!

2号窗口--->售票结束!

1号窗口--->售票结束!

4号窗口--->售票结束!

这个时候,我们可以看出,同一张票在不对票数进行保护的时候,会出现同一张票会被售出多次的情况。

因为线程调度中的不确定性,所以在演示上面的代码的时候,出现的运行结果会有不同。

1、实现线程安全的方式

同步代码块package com.bpan.spring.beans.thread;

import com.sun.org.apache.regexp.internal.recompile;

public class ThreadSynchronizedSecurity {

static int tickets = 10;

class SellTickets implements Runnable{

@Override

public void run() {

// 同步代码块

while(tickets > 0) {

synchronized (this) {

//                    System.out.println(this.getClass().getName().toString());

if (tickets <= 0) {

return;

}

System.out.println(Thread.currentThread().getName()+"--->售出第:  "+tickets+" 票");

tickets--;

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

if (tickets <= 0) {

System.out.println(Thread.currentThread().getName()+"--->售票结束!");

}

}

}

}

public static void main(String[] args) {

SellTickets sell = new ThreadSynchronizedSecurity().new SellTickets();

Thread thread1 = new Thread(sell, "1号窗口");

Thread thread2 = new Thread(sell, "2号窗口");

Thread thread3 = new Thread(sell, "3号窗口");

Thread thread4 = new Thread(sell, "4号窗口");

thread1.start();

thread2.start();

thread3.start();

thread4.start();

}

}

输出的结果可以自行调试。

2、实现线程安全的方式

同步方法package com.bpan.spring.beans.thread;

public class ThreadSynchroniazedMethodSecurity {

static int tickets = 10;

class SellTickets implements Runnable{

@Override

public void run() {

//同步方法

while (tickets > 0) {

synMethod();

try {

Thread.sleep(100);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if (tickets<=0) {

System.out.println(Thread.currentThread().getName()+"--->售票结束");

}

}

}

synchronized void synMethod() {

synchronized (this) {

if (tickets <=0) {

return;

}

System.out.println(Thread.currentThread().getName()+"---->售出第 "+tickets+" 票 ");

tickets-- ;

}

}

}

public static void main(String[] args) {

SellTickets sell = new ThreadSynchroniazedMethodSecurity().new SellTickets();

Thread thread1 = new Thread(sell, "1号窗口");

Thread thread2 = new Thread(sell, "2号窗口");

Thread thread3 = new Thread(sell, "3号窗口");

Thread thread4 = new Thread(sell, "4号窗口");

thread1.start();

thread2.start();

thread3.start();

thread4.start();

}

}

输出结果可以自行调试。

3、实现线程安全的方式

Lock锁机制,通过创建Lock对象,采用lock()加锁,unlock()解锁,来保护指定的代码块package com.bpan.spring.beans.thread;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class ThreadLockSecurity {

static int tickets = 10;

class SellTickets implements Runnable{

Lock lock = new ReentrantLock();

@Override

public void run() {

// Lock锁机制

while(tickets > 0) {

try {

lock.lock();

if (tickets <= 0) {

return;

}

System.out.println(Thread.currentThread().getName()+"--->售出第:  "+tickets+" 票");

tickets--;

} catch (Exception e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}finally {

lock.unlock();

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

if (tickets <= 0) {

System.out.println(Thread.currentThread().getName()+"--->售票结束!");

}

}

}

public static void main(String[] args) {

SellTickets sell = new ThreadLockSecurity().new SellTickets();

Thread thread1 = new Thread(sell, "1号窗口");

Thread thread2 = new Thread(sell, "2号窗口");

Thread thread3 = new Thread(sell, "3号窗口");

Thread thread4 = new Thread(sell, "4号窗口");

thread1.start();

thread2.start();

thread3.start();

thread4.start();

}

}

以上的三种实现线程安全的方式你都了解了吗?更多相关知识,可以继续关注奇Q工具网的java架构师栏目来了解呢!

推荐阅读:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值