线程的安全问题

        多线程在并发处理共享数据,会对数据进行修改或者读取导致共享的数据发生了无法预料的变化。案例:有三个窗口同时售票,每个窗口都共享着一定票数,某个线程操着当前票数还没有对其改变,就有其他线程把当前票就修改了,就会出现负票情况,这就是线程不安全的。

解决方案synchronized 解决

        synchronized直译同步的意思,有两种方法1、同步方法 2、同步代码块;注: synchronized(?),括号里面的?是同一个对象,我们称之为锁是一个对象该对象可以是任意对象但必须保证是同一对象。举例:火车上有个厕所当我们去上厕所是需要挂锁别人没钥匙打不开只有你上完厕所把锁打开别人才能进去继续上锁一次类推。

目录

解决方案synchronized 解决

一、同步代码块

1、实现接口

2、继承

二、同步方法

1、实现接口

2、继承


 

一、同步代码块

1、实现接口

       (1) 当前Object就是锁对象,该S1对象只new 了一次,Object也只new了一次,所以他是同一把锁,也可以用this

package cn;

class S1 implements Runnable{
     private int t=200;
     Object o=new Object();
    @Override
    public void run() {
       synchronized(o){
           while(true){
               if(t>0){
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println(Thread.currentThread().getName()+": 票数为:"+t);
                   t--;
               }else{
                   break;
               }
           }
       }
    }
}
public class SynchronizedTest {
    public static void main(String[] args) {
        S1 s = new S1();
        Thread t=new Thread(s);
        Thread t1=new Thread(s);
        Thread t2=new Thread(s);
        t.setName("1号口");
        t1.setName("2号口");
        t2.setName("3号口");
        t.start();
        t1.start();
        t2.start();
    }
}

 (2)S1.class在JVM加载过程中只加载一次

package cn;

class S1 implements Runnable{
     private int t=200;

    @Override
    public void run() {
       synchronized(S1.class){
           while(true){
               if(t>0){
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println(Thread.currentThread().getName()+": 票数为:"+t);
                   t--;
               }else{
                   break;
               }
           }
       }
    }
}
public class SynchronizedTest {
    public static void main(String[] args) {
        S1 s = new S1();
        Thread t=new Thread(s);
        Thread t1=new Thread(s);
        Thread t2=new Thread(s);
        t.setName("1号口");
        t1.setName("2号口");
        t2.setName("3号口");
        t.start();
        t1.start();
        t2.start();
    }
}

2、继承

(1)S2.class在JVM加载过程中只加载一次,可以用private static Object o=new Object,静态的,不能像接口用this这是指当前对象,当前对象s2被new 了三次,不是同一把锁

package cn;
class S2 extends Thread{
    private static int t=200;
    private static Object o=new Object();
    @Override
    public void run() {
        synchronized(o){
            while(true){
                if(t>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+": 票数为:"+t);
                    t--;
                }else{
                    break;
                }
            }
        }
    }
}
public class SynchronizedDemo {
    public static void main(String[] args) {
        S2 t=new S2();
        S2 t1=new S2();
        S2 t2=new S2();
        t.setName("1号口");
        t1.setName("2号口");
        t2.setName("3号口");
        t.start();
        t1.start();
        t2.start();
    }

}
package cn;
class S2 extends Thread{
    private static int t=200;

    @Override
    public void run() {
        synchronized(S2.class){
            while(true){
                if(t>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+": 票数为:"+t);
                    t--;
                }else{
                    break;
                }
            }
        }
    }
}
public class SynchronizedDemo {
    public static void main(String[] args) {
        S2 t=new S2();
        S2 t1=new S2();
        S2 t2=new S2();
        t.setName("1号口");
        t1.setName("2号口");
        t2.setName("3号口");
        t.start();
        t1.start();
        t2.start();
    }

}

二、同步方法

1、实现接口

(1)这相当于锁是this

package cn;

class S1 implements Runnable{
     private int t=200;
    public void run() {
        while (true) {
            titck();
        }
    }
    private synchronized  void titck(){
        if(t>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+": 票数为:"+t);
            t--;
        }

    }
}
public class SynchronizedTest {
    public static void main(String[] args) {
        S1 s = new S1();
        Thread t=new Thread(s);
        Thread t1=new Thread(s);
        Thread t2=new Thread(s);
        t.setName("1号口");
        t1.setName("2号口");
        t2.setName("3号口");
        t.start();
        t1.start();
        t2.start();
    }
}

2、继承

(2)相当于锁是S2.class

package cn;
class S2 extends Thread{
    private static int t=200;
    @Override
    public void run() {
        while (true) {
            titck();
        }
    }
        private  static synchronized   void titck(){
                if(t>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+": 票数为:"+t);
                    t--;
                }
        }

}


public class SynchronizedDemo {
    public static void main(String[] args) {
        S2 t=new S2();
        S2 t1=new S2();
        S2 t2=new S2();
        t.setName("1号口");
        t1.setName("2号口");
        t2.setName("3号口");
        t.start();
        t1.start();
        t2.start();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值