Java多线程中,synchronized同步代码块解决多线程数据安全问题

  1. synchronized同步代码块解决多线程数据安全问题

synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁。

synchronized(任意对象)
{
 多条语句操作共享数据的代码 
}
代码演示
public class SellTicket implements Runnable {
    private  int  tickets=100;
    private Object obj = new Object();
    @Override
    public void run() {
            while(true){
                synchronized (obj){
                    if(tickets>0){
                        try {
                            Thread.sleep(100);
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                        tickets--;
                    }
                }

            }
    }
}
public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st= new SellTicket();

        Thread t1=new Thread(st,"窗口1");
        Thread t2=new Thread(st,"窗口2");
        Thread t3=new Thread(st,"窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

 2、同步方法解决数据安全问题

同步方法:就是把synchronized关键字加到方法上
修饰符 synchronized 返回值类型 方法名(方法参数) { 
    方法体; 
}

 

同步静态方法:就是把synchronized关键字加到静态方法上

 

修饰符 static synchronized 返回值类型 方法名(方法参数) { 
    方法体; 
}

 代码示例:

 

public class SellTicket implements Runnable {
    private  int  tickets=100;
    private Object obj = new Object();
    @Override
    public void run() {
            while(true){
                SellTicket(tickets);
            }
    }
    private  static synchronized void SellTicket( int tickets) {
        if (tickets > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
            tickets--;
        }
    }
}
public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st= new SellTicket();

        Thread t1=new Thread(st,"窗口1");
        Thread t2=new Thread(st,"窗口2");
        Thread t3=new Thread(st,"窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

 3、生产者-消费者线程案例,模拟牛奶箱放牛奶

案例需求
生产者消费者案例中包含的类:
奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储牛奶和获取牛奶的操作
生产者类(Producer):实现Runnable接口,重写run()方法,调用存储牛奶的操作
消费者类(Customer):实现Runnable接口,重写run()方法,调用获取牛奶的操作
测试类(BoxDemo):里面有main方法,main方法中的代码步骤如下
①创建奶箱对象,这是共享数据区域
②创建消费者创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
③对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用获取牛奶的操作
④创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递
⑤启动线程
public class Box {
    private  int milk;             //定义一个成员变量,表示第x瓶奶
    private  boolean state = false;//定义一个成员变量,表示奶箱的状态
    public synchronized void put(int milk){
        if(state){
            try{
                wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        this.milk=milk;
        System.out.println("送第"+milk+"牛奶进入奶箱");
        state=true;
        notifyAll();
    }

    public synchronized void get(){
            if(!state){
                try{
                    wait();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        System.out.println("用户拿到了第"+this.milk+"瓶牛奶");
            state=false;
            notifyAll();
    }
}
public class Producer implements Runnable {
    private  Box box;
    public Producer(Box b){
        this.box=b;
    }
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            box.put(i);
        }
    }
}
public class Customer implements Runnable {
    private Box box;
    public Customer(Box box){
        this.box=box;
    }
    @Override
    public void run() {
        while (true){
            box.get();
        }
    }
}
public class BoxDemo {
    public static void main(String[] args) {
        Box box=new Box();
        Producer p=new Producer(box);
        Customer c=new Customer(box);

        Thread t1=new Thread(p);
        Thread t2=new Thread(c);

        t1.start();
        t2.start();
    }
}
原文地址:https://www.cnblogs.com/newway644617704/p/14089843.html