synchronized和Lock的区别及生命周期间的转换问题

synchronized和Lock的区别

synchronized和Lock的区别:
1、Lock是个接口,而synchronized是java关键字,synchronized是内置语言实现
2、synchronized是jdk1.0版本提供的,Lock是jdk1.5提供的
3、synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象的发生;而Lock在发生异常时,如果没有主动通过unlock()去释放锁,则很有可能造成死锁现象,因此使用Lock时需要在finally块中释放锁
4、Lock可以让等待锁的线程相应中断;而synchronized不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断
synchronized关键字的使用:

//synchronized语法块
		synchronized(对象){
			需要加锁的代码
		}
//	synchronized可以修饰方法
	强调:建议锁的范围越小越好

以下为synchronized的两个使用案例:synchronized语法块

public class TestThread03 {
    public static void main(String[] args) {
        MyThread04 mt = new MyThread04();
        Thread m1 = new Thread(mt);
        Thread m2 = new Thread(mt);
        m1.start();
        m2.start();
    }
}
class MyThread04 extends Thread{
    private int id;
    private Object key = new Object();
    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            synchronized (key) {
                id++;
            }
        }
        System.out.println(Thread.currentThread().getName() + "--结果是:"+ id);
    }
}

synchronized修饰方法

public class TestThread03 {
    public static void main(String[] args) {
        MyThread04 mt = new MyThread04();
        Thread m1 = new Thread(mt);
        Thread m2 = new Thread(mt);
        m1.start();
        m2.start();
    }
}
class MyThread04 extends Thread{
    private int id;
    private Object key = new Object();
     @Override
    public synchronized void run() {
        for (int i = 0; i < 1000000; i++) {
            id++;
        }
        System.out.println(Thread.currentThread().getName() + "--结果是:"+ id);
    }
}

Lock由jdk1.5提供的
lock接口的实现必须实现他的子类ReentrantLock()方法

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

public class TestThread04 {
    public static void main(String[] args) {
        MyThread05 mt = new MyThread05();
        Thread m1 = new Thread(mt);
        Thread m2 = new Thread(mt);

        m1.start();
        m2.start();
    }
}
class MyThread05 extends Thread{
    private int id;
    private Object key = new Object();
    // 冲入锁 jdk1.5提供的
    Lock lock = new ReentrantLock();
    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            try {
                // 加锁
                lock.lock();
                id++;
            } finally {
                // 释放锁
                lock.unlock();
            }
        }
        System.out.println(Thread.currentThread().getName() + "--结果是:"+ id);
    }
}

线程生命周期及转换问题

概述:
当线程被创建以后,它不是一启动(start)就进入运行状态的,也不是一直处于执行状态。在线程的生命周期中,它要经过new(创建线程) 、ready(就绪) 、running(运行)、 block(阻塞) 、destroy(销毁)这五种状态。当线程进入运行状态后,它不是一直“霸占”CPU运行,一般的操作系统是采用抢占式的方式来让线程获得CPU。所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞、就绪之间切换。
线程的创建:
当程序使用new关键字创建一个线程以后,该线程就处于新建状态,此时它和其他的JAVA对象一样,仅仅由JAVA虚拟机为其分配内存,并初始化成员变量的值。此时的线程对象没有表现出任何线程的动态特征,程序也不会执行线程的线程执行体。
运行和阻塞状态:
当处于就绪状态的线程获得CPU,它就会执行run()方法(所以run()方法是由线程获得CPU以后自动执行),线程就进入了运行状态。如果一个计算机只有一个CPU,那么在任意时刻只有一个线程处于运行状态。相对的,如果有多个CPU,那么在同一时刻就可以有多个线程并行执行。
当正在执行的线程被阻塞以后,其他线程可以获得执行的机会,被阻塞的线程会在合适的时候进入就绪状态,而不是进入运行状态。
线程间的转换图:
在这里插入图片描述
线程死亡:
1、run()/call()方法执行完成,线程正常结束;
2、直接调用线程的stop()方法结束该线程——该方法容易导致死锁,通常不建议使用。
注意:一旦当子线程启动以后,它就拥有和主线程一样的地位,它不会受主线程的影响。线程提供了一个isAlive()方法,当调用线程对象的isAlive()方法,如果该线程处于就绪、运行、阻塞三种状态时,该方法返回true;当线程处于新建、死亡两种状态时,返回false。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值