Java多线程学习--04

说明:参考《Java多线程核心技术》

4、dirtyRead

发生脏读情况是在读取变量时,此值已经被其他的线程给修改了。

public class DirtyRead extends Thread{
    private PublicVaria publicVaria;
    public DirtyRead(PublicVaria publicVaria) {
        super();
        this.publicVaria = publicVaria;
    }

    @Override
    public void run(){
        super.run();
        publicVaria.setValue("B", "BB");
    }
}
public class PublicVaria {
    private String userName = "A";
    private String passWord = "AA";
    synchronized public void setValue (String userName, String passWord) {
        try {
            this.userName = userName;
            Thread.sleep(5000);
            this.passWord = passWord;
            System.out.println(Thread.currentThread().getName() + "userName --"
                    + userName + "--" + "password" + "--" + passWord);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void getValue () {
        System.out.println(Thread.currentThread().getName() + userName +"--" + passWord);
    }
}
public class DirtyReadTest {
    public static void main(String[] args) {
        try {
            PublicVaria publicVaria = new PublicVaria();
            DirtyRead threadA = new DirtyRead(publicVaria);
            threadA.start();
            // change the value can influence the result
            Thread.sleep(2000);
            publicVaria.getValue();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
 mainB--AA
 Thread-0userName --B--password--BB
 */

出现脏读的原因是getValue()方法不是同步的,所以在threadA线程sleep的时候,出现了脏读。

5、可重入锁

关键字synchronized具有锁重入的功能,即在使用synchronized时,当一个线程得到一个对象以后,再次请求此对象锁时,可以再次得到该对象的锁。说明了在一个synchronized方法/块的内部使用奔雷的其他synchronized方法/块时,是可以永远得到锁的。

public class Reentrant {

    synchronized public void reentrant1Service1() {
        System.out.println("reentrant1Service1");
        reentrant1Service2();
    }

    synchronized public void reentrant1Service2() {
        System.out.println("reentrant1Service2");
        reentrant1Service3();
    }

    synchronized public void reentrant1Service3(){
        System.out.println("reentrant1Service3");
    }

}
public class ReentrantThread extends Thread {
    @Override
    public void run(){
        Reentrant reentrant = new Reentrant();
        reentrant.reentrant1Service1();
    }
}

public class ReentrantThreadTest {
    public static void main(String[] args) {
        ReentrantThread thread = new ReentrantThread();
        thread.start();
    }
}
/**
 reentrant1Service1
 reentrant1Service2
 reentrant1Service3
 */

说明:“可重入锁”: 自己可以再次获得自己的内部锁。假设synchronized不是可重入锁的话,线程就会发生死锁。因为有条线程获得了当前对象的锁,且此时的锁还没有释放,当其再次想要获得这个对象的锁时,还是可以获取到的,如果获取不到,就会发生死锁线程。

6、异常时,锁的自动释放
public class ThreadA extends Thread{
    private ExceptionThread exceptionService;

    public ThreadA(ExceptionThread exceptionService){
        super();
        this.exceptionService = exceptionService;
    }

    @Override
    public void run(){
        exceptionService.exceptionThread();
    }
}
public class ThreadB extends Thread{

    private ExceptionThread exceptionService;

    public ThreadB (ExceptionThread exceptionService){
        super();
        this.exceptionService = exceptionService;
    }

    @Override
    public void run(){
        exceptionService.exceptionThread();
    }
}
public class ExceptionThread {
    synchronized public void exceptionThread (){
        if (Thread.currentThread().getName().equals("a")) {
            System.out.println("ThreadName = " + Thread.currentThread().getName()
            + "start time = " + System.currentTimeMillis());

            int i = 1;
            while (i == 1){
                if (("" + Math.random()).substring(0, 8).equals("0.123456")){
                    System.out.println("ThreadName = " + Thread.currentThread().getName() +
                            " exception Time = " + System.currentTimeMillis());
                    Integer.parseInt("a");
                }
       		 }
   		 }else {
            System.out.println("ThreadB run time = " + System.currentTimeMillis());
        }
    }
}
public class ExceptionThreadTest {
    public static void main(String[] args) {
        try {
            ExceptionThread thread = new ExceptionThread();
            ThreadA a = new ThreadA(thread);
            a.setName("a");
            a.start();
            Thread.sleep(500);
            ThreadB b = new ThreadB(thread);
            b.setName("b");
            b.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
ThreadName = astart time = 1546669373655
ThreadName = a exception Time = 1546669373889
Exception in thread "a" java.lang.NumberFormatException: For input string: "a"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.parseInt(Integer.java:615)
	at com.paojiaojiang.exception.ExceptionThread.exceptionThread(ExceptionThread.java:19)
	at com.paojiaojiang.exception.ThreadA.run(ThreadA.java:18)
ThreadB run time = 1546669374170
 */

在线程a出现异常时,主动释放当前持有的锁,线程b进入打印方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值