淘先锋技术网

首页 1 2 3 4 5 6 7
线程同步:
模拟售票程序出现问题:
            当多个线程同时访问共享数据时,产生无序、重复、超额售票等多线程安全问题
解决:将多个线程需要访问的共享数据,包装起来视为一个整体,确保一次只有一个线程执行流访问共享数据
Java为上述问题提供了相应的解决办法:
    1、同步代码块
         synchronized(同步监视器){
            //多个线程需要访问的共享数据
         }
         同步监视器:俗称“锁” ,可以使用任意类型的对象充当。但是必须保证多个线程持有 同一把锁(同一个对象)

    2、同步方法
    3、同步锁 Lock

package Thread;

public class TicketWindow2 implements Runnable{
    int tick=100;
    Object obj=new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            }
        }
    }
}
package Thread;

public class TicketWindowTest2 {
    public static void main(String[] args) {
        TicketWindow2 tw2=new TicketWindow2();
        Thread t1=new Thread(tw2,"一号窗口");
        t1.start();
        Thread t2=new Thread(tw2,"二号窗口");
        t2.start();
        Thread t3=new Thread(tw2,"三号窗口");
        t3.start();

    }
}

 同步方法 :

在方法声明处加 synchronized 关键字
                如:
                    public synchronized void show() {
                 }
package Thread;

public class TicketWindow2 implements Runnable{
    int tick=100;
    Object obj=new Object();
    @Override
    public void run() {
        while (true){
           /* synchronized (obj){
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            }*/
            show();
        }
    }
    public synchronized void show(){
        if (tick>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
        }
    }
}

同步锁:

Lock为接口,创建实例

unlock一定要执行,所以放到try-catch-finally中

package Thread;

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

public class TicketWindow2 implements Runnable{
    int tick=100;
    Object obj=new Object();
    Lock l=new ReentrantLock();
    @Override
    public void run() {
        while (true){
           /* synchronized (obj){
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            }*/


//            show();

            l.lock();//上锁
            try {
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                l.unlock();//释放锁
            }

        }
    }
    public synchronized void show(){
        if (tick>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
        }
    }
}

 

当前的锁为悲观锁 

 

线程同步:
模拟售票程序出现问题:
            当多个线程同时访问共享数据时,产生无序、重复、超额售票等多线程安全问题
解决:将多个线程需要访问的共享数据,包装起来视为一个整体,确保一次只有一个线程执行流访问共享数据
Java为上述问题提供了相应的解决办法:
    1、同步代码块
         synchronized(同步监视器){
            //多个线程需要访问的共享数据
         }
         同步监视器:俗称“锁” ,可以使用任意类型的对象充当。但是必须保证多个线程持有 同一把锁(同一个对象)

    2、同步方法:在方法声明处加 synchronized 关键字
                    如:
                        public synchronized void show() {
                     }
                注意:非静态同步方法隐式的锁为 this(即当前对象)
                      静态同步方法的锁为对应类的Class实例
    3、同步锁 Lock

Exer:

银行有一个账户。
有两个储户分别向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额.
问题:该程序是否有安全问题,如果有,如何解决?
【提示】
1,明确哪些代码是多线程运行代码,须写入run()方法
2,明确什么是共享数据。
3,明确多线程运行代码中哪些语句是操作共享数据的。
package Exer;
/*
银行有一个账户。
有两个储户分别向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额.
问题:该程序是否有安全问题,如果有,如何解决?
【提示】
1,明确哪些代码是多线程运行代码,须写入run()方法
2,明确什么是共享数据。|
3,明确多线程运行代码中哪些语句是操作共享数据的。

 */
public class Exer {
    public static void main(String[] args) {
        Account account=new Account();
        Customer ca=new Customer(account);
        Customer cb=new Customer(account);
        new Thread(ca,"用户A").start();
        new Thread(cb,"用户B").start();

    }
}
package Exer;

public class Account {
    private double balance;

    public Account() {
    }

    public Account(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
    //存款
    public synchronized void deposit(double amount){
        balance+=amount;
        System.out.println(Thread.currentThread().getName()+"成功存入:"+amount+"余额为:"+balance);
    }
}
package Exer;

public class Customer implements Runnable {
    private Account account;

    public Customer() {
    }

    public Customer(Account account) {
        this.account = account;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        for (int i = 0; i <3; i++) {
            account.deposit(1000);
        }
    }
}

 

 补充:互斥锁

 

 

线程的死锁问题: 

 

 

package Thread;

public class DeadLockTest {
    public static void main(String[] args) {
        DeadLock dl=new DeadLock();
        new Thread(dl).start();
        new Thread(dl).start();
    }
}
class DeadLock implements  Runnable{
    boolean flag=true;
    static Object obj1=new Object();//共享数据1
    static Object obj2=new Object();//共享数据2
    @Override
    public void run() {
        if (flag){
            synchronized (obj1){
                System.out.println("获取共享数据1,等待共享数据2....");

                synchronized (obj2){
                    System.out.println("-----------------------");
                }
            }
        }else {
            synchronized (obj2){
                System.out.println("获取共享数据2,等待共享数据1....");

                synchronized (obj1){
                    System.out.println("*************************");
                }

            }
        }
    }
}

------------------------------------------------------------------------------------------------------------ 

 

 

 将问题放大: