java中ReentrantLock类的tryLock和tryLock的例子和用法

ReentrantLock类的tryLock和tryLock(时间)
马克-to-win:tryLock的方法就是试一下,如果能得到锁,就返回真,如果当时得不到,马上就返回假,绝不等。tryLock(时间)的用法就是在规定的时间内设法得到锁。如果在规定的时间内最终不能得到锁,就返回假。注意,这个方法是可以被打断的,打断后的处理方法和上面的例子 lockInterruptibly的处理一样。马克- to-win:马克 java社区:防盗版实名手机尾号: 73203。

例1.9.8_a:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
class A {
    private ReentrantLock lock = new ReentrantLock();
    int ticketNum = 10;
    public void buyOne() {
        System.out.println("just before lock.lockInterruptibly();");
        boolean succeed = lock.tryLock();
        if (succeed) {
            System.out.println(Thread.currentThread().getName()
                    + "ticketNum is" + ticketNum);
            if (ticketNum > 0) {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ticketNum--;
                System.out
                        .println("模仿select * from table for update,执行的很慢,买了一张"
                                + Thread.currentThread().getName()
                                + "ticketNum is" + ticketNum);
            }
            lock.unlock();
        }else{
            System.out.println("没获得锁,一张");
        }
    }

    public void buyBatch(int num) throws InterruptedException {
        System.out.println("just before lock.lockInterruptibly();");
        boolean succeed = false;
        boolean sleepSucceed = false;
        succeed = lock.tryLock(2, TimeUnit.SECONDS);
        if (succeed) {
            System.out.println("Thread.currentThread().getName()+ticketNum is"
                    + ticketNum);
            try {
                Thread.sleep(5000);
                sleepSucceed=true;
            } catch (InterruptedException e) {
                System.out.println("已经获得了锁了,几张的睡觉被打断,表示预备工作没做好,什么也不买");
            }
            if (ticketNum >= num&&sleepSucceed) {
                ticketNum = ticketNum - num;
                System.out
                        .println("模仿select * from table for update,执行的很慢,买了几张"
                                + Thread.currentThread().getName()
                                + "ticketNum is" + ticketNum);
            }
            lock.unlock();
        }else{
            System.out.println("没获得锁,几张");
        }
    }
}

class MyThread1 extends Thread {
    A a;
    public MyThread1(A a) {
        this.a = a;
    }
    public void run() {
        a.buyOne();
    }
}

class MyThread2 extends Thread {
    A a;
    public MyThread2(A a) {
        this.a = a;
    }
    public void run() {
        try {
            a.buyBatch(3);
        } catch (InterruptedException e) {
            System.out.println("正要获得锁的过程当中呢,几张的线程被打断");
        }
    }
}
public class TestMark_to_win {
    public static void main(String[] args) throws InterruptedException {
        MyThread1[] threads = new MyThread1[2];
        A a = new A();
        for (int i = 0; i < 2; i++) {
            threads[i] = new MyThread1(a);
        }
        MyThread2 myThread2 = new MyThread2(a);
        threads[0].start();
Thread.sleep(50);
        myThread2.start();
        threads[1].start();
//        Thread.sleep(50);
//        myThread2.interrupt();
    }
}




(这种情况是tryLock(2, TimeUnit.SECONDS);根本没得到锁)运行结果:
just before lock.lockInterruptibly();
Thread-0ticketNum is10
just before lock.lockInterruptibly();
just before lock.lockInterruptibly();
没获得锁,一张
没获得锁,几张
模仿select * from table for update,执行的很慢,买了一张Thread-0ticketNum is9



例1.9.8_b:(只需要把上面实验的主程序改变一下就行,其他都不用变。)

public class TestMark_to_win {
    public static void main(String[] args) throws InterruptedException {
        MyThread1[] threads = new MyThread1[2];
        A a = new A();
        for (int i = 0; i < 2; i++) {
            threads[i] = new MyThread1(a);
        }
        MyThread2 myThread2 = new MyThread2(a);
        threads[0].start();
        Thread.sleep(50);
        myThread2.start();
        threads[1].start();
        Thread.sleep(50);
        myThread2.interrupt();
    }
}

(这种情况是tryLock(2, TimeUnit.SECONDS);正要获得锁的过程当中被打断了)运行结果:
just before lock.lockInterruptibly();
Thread-0ticketNum is10
just before lock.lockInterruptibly();
just before lock.lockInterruptibly();
没获得锁,一张
正要获得锁的过程当中呢,几张的线程被打断
模仿select * from table for update,执行的很慢,买了一张Thread-0ticketNum is9




例1.9.8_c:
public class TestMark_to_win {
    public static void main(String[] args) throws InterruptedException {
        MyThread1[] threads = new MyThread1[2];
        A a = new A();
        for (int i = 0; i < 2; i++) {
            threads[i] = new MyThread1(a);
        }
        MyThread2 myThread2 = new MyThread2(a);
      
        myThread2.start();
        Thread.sleep(50);
        threads[0].start();
        threads[1].start();
//        Thread.sleep(50);
//        myThread2.interrupt();
    }
}


(这种情况是tryLock(2, TimeUnit.SECONDS);获得了锁)运行结果:

just before lock.lockInterruptibly();
Thread.currentThread().getName()+ticketNum is10
just before lock.lockInterruptibly();
没获得锁,一张
just before lock.lockInterruptibly();
没获得锁,一张
模仿select * from table for update,执行的很慢,买了几张Thread-2ticketNum is7




例1.9.8_d:

public class TestMark_to_win {
    public static void main(String[] args) throws InterruptedException {
        MyThread1[] threads = new MyThread1[2];
        A a = new A();
        for (int i = 0; i < 2; i++) {
            threads[i] = new MyThread1(a);
        }
        MyThread2 myThread2 = new MyThread2(a);
      
        myThread2.start();
        Thread.sleep(50);
        threads[0].start();
        threads[1].start();
        Thread.sleep(50);
        myThread2.interrupt();
    }
}


(这种情况是tryLock(2, TimeUnit.SECONDS);已经获得了锁,【注意虽然写的是2秒,但是myThread2是排在队列里第一个的,根本不用等,更别说是等2秒,2秒是真正等时的极限。】正在干事的的过程当中被打断了)运行结果:


just before lock.lockInterruptibly();
Thread.currentThread().getName()+ticketNum is10
just before lock.lockInterruptibly();
没获得锁,一张
just before lock.lockInterruptibly();
没获得锁,一张
已经获得了锁了,几张的睡觉被打断,表示预备工作没做好,什么也不买



volatile关键字与原子操作

volatile关键字到底是干什么的?(新手可略过)

我们先简要了解一下java虚拟机的内存模型。就像数据从物理内存拷贝到cpu高速缓存,进行操作完,再把数据返回到内存一样,为了屏蔽CPU高速缓存和内存复杂细节且赢得跨平台的效果,java把所有的变量都存在主存(相当于物理内存)当中,每个线程都有自己的工作内存(相当于CPU高速缓存)。线程在自己的工作内存做操作,不能直接对主存进行操作,最后把结果返回到主存。如果一个变量有volatile(易变的意思)修饰词,这意味着当有一个线程修改了这个变量,系统会把工作内存当中的变化强制立刻反应在主存当中。其他线程要想读这个变量,也会被强迫读变化了的新值。volatile其实就保证了此变量无论怎么变,任何线程看都是最新的。当两个线程,根据一个共同的信号,做互动时,一定要加volatile,保证这个信号是最新的。

volatile,有人说能够控制程序的语句有序性,但jvm并不能保证在所有的平台上都能够做到这一点,所以我的书中就不赘述了。既然volatile控制程序语句的有序性不能保证所有的平台都正确运行,基于它的技术“双重检查锁”创建单态对象也就变得不可靠了,本书也就不覆盖了。