36.1 线程锁

一、没用锁之前出现的问题

package day34_thread_线程.线程锁;

/*
 * t1,t2,t3
 * 假设只剩一张票
 * t1过来了,他一看有票,他就进来了,但是他突然肚子不舒服,然后他就去上卫生间了
 * t2也过来了,他一看也有票,他也进来了,但是他的肚子也不舒服,他也去上卫生间了
 *
 * t1上完了卫生间回来了,开始售票
 *     tickets = 0;
 * t2也上完卫生间回来了,他也进行售票
 *  tickets = -1;
 *
 *
 */

public class SleepThread implements Runnable {
    int nums = 20;

    @Override
    public void run() {
//        if(num > 0) {
//            for(int i=0;i<100;i++) {
//                System.out.println(Thread.currentThread().getName() + ":" + i);
//            }
        while(true) {
            if(nums > 0) {
                try {
                    Thread.sleep(100);
            } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + ":" + nums--);
            }else {
                System.exit(0);
            }
        }
    }
}
package day34_thread_线程.线程锁;
/*
 * 模拟火车站售票
 *
 *        分析:
 *                首相需要有火车票的总数量,每售出一张则数量减一
 *                当火车票的数量小于1的时候,停止售票
 *                使用多线程模拟多个窗口进行售票
 *                当火车票全部售完,火车站也一样敞开大门欢迎我们
 *
 *        static void sleep(long millis) : 让当前线程睡一会
 */
public class SleepDemo {
    public static void main(String[] args) {
        SleepThread st = new SleepThread();
        Thread t = new Thread(st);
        t.setName("窗口1");
        t.start();

        Thread t1 = new Thread(st);
        t1.setName("窗口2");
        t1.start();

        Thread t2 = new Thread(st);
        t2.setName("窗口3");
        t2.start();

    }
}

输出:会出现票的争夺,

二、使用线程锁解决

synchronized是java中的一个关键字,修饰符。
synchronized:同步(锁),可以修饰代码块和方法,被修饰的代码块和方法一旦被某个线程访问,则直接锁住,其他的线程将无法访问

同步代码块:
  synchronized(锁对象){
     }

同步方法:
  public synchronized void method() {
    }

synchronized代码块又分为这么几种:synchronized(this),synchronized(className.class)和synchronized(Object obj)

* synchronized(this):修饰非静态方法,锁都在当前对象,只限制当前对象对该代码块的同步。

* synchronized(className.class 字节码对象):修饰静态方法,锁在类而不在类对象,只要是className类对象访问该代码块都被要求同步。

* synchronized(Object obj) :这时锁就是对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁

1. 代码块

package day34_thread_线程.线程锁;

public class SynchronizedThtread implements Runnable {
    //火车票数 20
    int num = 20;
    Object obj = new Object();

    @Override
    public void run() {

        while(true) {

            synchronized(obj) {
                try{Thread.sleep(100);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(num > 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + num--);
                }
            }

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

        Thread t = new Thread(st);
        t.setName("窗口1");
        t.start();

        Thread t1 = new Thread(st);
        t1.setName("窗口2");
        t1.start();

        Thread t2 = new Thread(st);
        t2.setName("窗口3");
        t2.start();
    }
}

输出:

线程切换,但是票数按顺序减少,符合要求

2.静态方法、非静态方法

package day34_thread_线程.线程锁;

public class SynFunThread implements Runnable {
    /*static int num = 100;*/
    int num = 20;

    @Override
    public void run() {
        method();
    }

    private synchronized void method() {
        while(true) {
            if(num > 0) {
                try{Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + ":" + num--);
            }
        }
    }

  /*  private static synchronized void method() {
        while(true) {
            if(num > 0) {
                try{Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + ":" + num--);
            }
        }
    }*/
}
public class SynFunDemo {
    public static void main(String[] args) {
        SynFunThread sft = new SynFunThread();

        Thread t = new Thread(sft);
        Thread t1 = new Thread(sft);
        Thread t2 = new Thread(sft);

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

输出:

原文地址:https://www.cnblogs.com/longesang/p/11340919.html