线程安全问题的例子以及解决方案示例代码

发布时间 2024-01-12 09:37:56作者: 话祥

1.多线程安全问题,出现重复卖票的现象

package net.bbd.spider.lock;


public class Ticket implements Runnable {
    static Integer tickets = 10;

    @Override
    public void run() {
        while(tickets > 0) {
            if (tickets <= 0) {
                return;
            }
            System.out.println(Thread.currentThread().getName()+"--->售出第:  "+tickets+" 票");
            tickets--;
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (tickets <= 0) {
                System.out.println(Thread.currentThread().getName()+"--->售票结束!");
            }
        }
    }

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(ticket,"线程名称" + 1).start();
        new Thread(ticket,"线程名称" + 2).start();
        new Thread(ticket,"线程名称" + 3).start();
        new Thread(ticket,"线程名称" + 4).start();
    }
}

2.使用synchronized关键字做线程安全控制

package net.bbd.spider.lock;


public class TicketSyn implements Runnable {
    static Integer tickets = 10;

    @Override
    public void run() {
        while(tickets > 0) {
            synchronized (this) {
                if (tickets <= 0) {
                    return;
                }
                System.out.println(Thread.currentThread().getName()+"--->售出第:  "+tickets+" 票");
                tickets--;
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (tickets <= 0) {
                System.out.println(Thread.currentThread().getName()+"--->售票结束!");
            }
        }
    }

    public static void main(String[] args) {
        TicketSyn ticket = new TicketSyn();
        new Thread(ticket,"线程名称" + 1).start();
        new Thread(ticket,"线程名称" + 2).start();
        new Thread(ticket,"线程名称" + 3).start();
        new Thread(ticket,"线程名称" + 4).start();
    }
}

3.使用ReentrantLock对象做线程安全控制

package net.bbd.spider.lock;


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TicketReentrantLock implements Runnable {
    static Integer tickets = 10;
    Lock lock = new ReentrantLock();
@Override
public void run() { //System.out.println(Thread.currentThread().getName()+"--->锁锁锁: " + lock); // Lock锁机制 while(tickets > 0) { try { lock.lock(); if (tickets <= 0) { return; } System.out.println(Thread.currentThread().getName()+"--->售出第: " + tickets + " 票"); tickets--; } catch (Exception e1) { e1.printStackTrace(); }finally { lock.unlock(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } if (tickets <= 0) { System.out.println(Thread.currentThread().getName()+"--->售票结束!"); } } public static void main(String[] args) { TicketReentrantLock ticket = new TicketReentrantLock(); new Thread(ticket,"线程名称" + 1).start(); new Thread(ticket,"线程名称" + 2).start(); new Thread(ticket,"线程名称" + 3).start(); new Thread(ticket,"线程名称" + 4).start(); } }

4.使用写锁ReentrantReadWriteLock做线程安全控制

package net.bbd.spider.lock;


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TicketWriteLock implements Runnable {
    static Integer tickets = 10;
    ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    Lock writeLock = readWriteLock.writeLock();
@Override
public void run() { // System.out.println(Thread.currentThread().getName()+"--->锁锁锁: " + writeLock); // Lock锁机制 while(tickets > 0) { try { writeLock.lock(); if (tickets <= 0) { return; } System.out.println(Thread.currentThread().getName()+"--->售出第: " + tickets + " 票"); tickets--; } catch (Exception e1) { e1.printStackTrace(); }finally { writeLock.unlock(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } if (tickets <= 0) { System.out.println(Thread.currentThread().getName()+"--->售票结束!"); } } public static void main(String[] args) { TicketWriteLock ticket = new TicketWriteLock(); new Thread(ticket,"线程名称" + 1).start(); new Thread(ticket,"线程名称" + 2).start(); new Thread(ticket,"线程名称" + 3).start(); new Thread(ticket,"线程名称" + 4).start(); } }