线程锁笔记

中午说的笔记来辣:

main线程会走完之后再走run的线程
当run线程加入join后就会把run线程走完再走

static修饰的东西在线程中层级相当于一个类方法

Thread t=new Thread(new FutureTask(new 类()),"");
Thread.State state = t.getState();
state是观察该线程是否运动,线程一旦死亡就无法再执行
)(括号的内容是小编在复习笔记中觉得较重要的,不喜滑走)

====================================================》

线程锁

synchronized和ReentrantLock的区别

Synchronized

例:
public synchronized void save(){}//static方法就是类锁,如果是非static则是对象锁;
synchronized (TestObject.class) {}//此处是类锁,无论怎么创建对象,都不会对同步代码块产生影响,因为所有的对象都是用的同一把锁;

1、该案例是多个线程“干一个活”,为了防止覆盖和超值,通过对象锁来维持线程秩序
在这里插入图片描述
2、怎么通过锁方法维护程序秩序,如果不维护会出现跟1一样的错误


public class TestThread03 {

    public synchronized  void exec()
    {


        System.out.println("线程开始:"+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 3; i++) {
            System.out.println("***");
        }

        System.out.println("线程结束:"+Thread.currentThread().getName());

    }

    public static void main(String[] args) {

        TestThread03 thread03 = new TestThread03();
        Thread t1 = new Thread(thread03, "线程1");
		t1.exec();
        Thread t2 = new Thread(thread03, "线程2");
		t2.exec();
        Thread t3 = new Thread(thread03, "线程3");
		t3.exec();

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

    }
}

3、同样是多个线程“干一个活”,为了防止覆盖和超值

/**
 * 对象锁,锁的是对象,如果对象发生了新的变化
 * 那么锁也会变成新的锁。
 *
 *
 * 类锁,锁的是类,无论对象怎么变化,锁都不会改变。
 * 类锁其实就是无论怎么创建对象,这些对象都共用同一把锁
 *
 *
 *
 */

public class Thread01 implements Runnable {

    Object o = new Object();
    @Override
    public void run() {
        /**
         *     Object o = new Object();
         *     synchronized(new Object())
         *     {
         *
         *     }
         *
         *      以上两种形式都会产生新的对象,每个线程的对象都是新的对象,
         *      也就是每个线程拥有不同的对象锁
         *
         */


        //线程A
       synchronized (o)//此处锁的是对象,所以要保证对象的唯一性,不要再创建同类型的对象

       {
           System.out.println("线程开始:"+Thread.currentThread().getName());
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           for (int i = 0; i < 3; i++) {
               System.out.println("***");
           }

           System.out.println("线程结束:"+Thread.currentThread().getName());
       }
    }
    public static void main(String[] args) {
        Thread01 thread01 = new Thread01();
        Thread t1 = new Thread(thread01, "线程1");
        Thread t2 = new Thread(thread01, "线程2");
        Thread t3 = new Thread(thread01, "线程3");

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

    }


}

4、synchronized (TestObject.class)的演示

public class Thread02 implements Runnable {


    Object tt = new Object();

    @Override
    public void run() {
        Object tt2 = new Object();

        /**
         *  synchronized (Object.class)
         *  {
         *
         *  }
         *  如果此处锁的是类,那就是类锁,类锁是可以创建无数个对象,但是并
         *  不会影响程序的正确性
         *
         *
         */

        //线程A
        synchronized (Object.class)// synchronized (this)this表示调用该方法对应的类的对象,this对应的对象是不会发生变化的

        {
            System.out.println("线程开始:"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 3; i++) {
                System.out.println("***");
            }

            System.out.println("线程结束:"+Thread.currentThread().getName());
        }
    }
    public static void main(String[] args) {
        
        Thread02 thread02 = new Thread02();
        Thread t1 = new Thread(thread02, "线程1");
        Thread t2 = new Thread(thread02, "线程2");
        Thread t3 = new Thread(thread02, "线程3");

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

    }
}

总结:
synchronized是自动锁,隐式锁
synchronized(this|object)对象锁
synchronized(类的名.class)全局锁
一般情况不建议使用synchronized锁,因为synchronized会降低程序性能

ReentrantLock
ReentrantLock是显式锁,手动开关,需要手动释放
使用ReentrantLock,JVM将会花费更少时间来调度线程,性能更好

例子:
我们通过买票来演示,大家都知道过节有的票是要抢的,但用线程怎么能让票在售票人员中即不会重票又不超票呢?


/**
 *
 * Lock显式锁,synchronized隐式锁
 *
 * 区别:
 * Lock需要手动设置和手动释放
 * synchronized 超出范围后会自动释放
 *
 * Lock只有代码块锁,synchronized有代码锁,还有方法锁
 *
 * Lock消耗的时间<synchronized代码块<synchronized方法
 *
 *
 */
public class Thread04 implements Runnable {

    int ticket=100;
    ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {

        while(true)
        {
            try {
                Thread.sleep(1000);

                lock.lock();//开启锁
                if(ticket>0)
                {
                    System.out.println("当前售票窗口:"+Thread.currentThread().getName()+"当前票数:"+(ticket--));
                }
                else
                {

                    System.out.println("售票完毕!");
                    break;
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();//释放锁
            }

        }
    }

    public static void main(String[] args) {
        Thread04 th = new Thread04();

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

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

    }
}

最后补充点小知识

小贴士:run方法和start方法区别:

Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,
就开始执行run()方法,这里的run()方法 称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值