Java多线程编程核心技术第二章笔记02

本文深入探讨Java中线程同步的各种实现方式,包括使用非this对象作为对象监视器、静态同步方法、synchronized代码块以及解决异步死循环问题。通过具体代码示例,解释了如何正确使用synchronized关键字来确保线程安全,同时讨论了String常量池特性和volatile关键字的作用。
摘要由CSDN通过智能技术生成

1.将任何对象作为对象监视器,也就是以锁非this对象



class Service {
    private String username;
    private String anyString = new String();
    public void setUsername(String username){
        try{
            synchronized (anyString){
                System.out.println("线程:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入同步块");
                this.username = username;
                Thread.sleep(3000);
                System.out.println("线程:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"离开同步块");
            }
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}

class ThreadA extends Thread{
    private Service service;
    public ThreadA(Service service){
        this.service = service;
    }

    public void run(){
        service.setUsername("a");
    }
}


class ThreadB extends Thread{
    private Service service;
    public ThreadB(Service service){
        this.service = service;
    }

    public void run(){
        service.setUsername("b");
    }
}



class Run{
    public static void main(String[] args){
        Service service = new Service();
        ThreadA threadA = new ThreadA(service);
        threadA.setName("A");
        threadA.start();
        ThreadB threadB = new ThreadB(service);
        threadB.setName("B");
        threadB.start();
    }
}

可见,使用synchronized(非this对象)同步代码块进行同步操作时,对象监视器必须是相同的对象,如果不是同一个对象监视器,运行的结果就是异步调用。这里是对anyString对象进行监视,由于为实例变量,所以可以保证为同一个对象。

把上述注释的的代码放到鼠标位置,这时就可以知道anyString为一个占变量,显然每次不可能是同一个对象,所以这里的代码块不会同步运行

2.静态同步synchronized方法与synchronized(class)代码块

关键字synchronized因应用在static方法上,是表示给所有类对象实例加锁,并不像前面所讲的对象锁那样,只给一个对象加锁。

对象锁:多个线程想要同步效果,必须保证对象锁是给同一个对象

3.String常量池特性

class Service {
    //由于常量池特性,两个线程都传相同参数,第二个和第一个其实是一样的
    public  void print(String stringParam){
        try{
            synchronized (stringParam){
                while(true){
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        }catch(InterruptedException e){

        }
    }
}

class ThreadA extends Thread{
    private Service service;
    public ThreadA(Service service){
        this.service = service;
    }

    public void run(){
        service.print("AA");
    }
}


class ThreadB extends Thread{
    private Service service;
    public ThreadB(Service service){
        this.service = service;
    }

    public void run(){
        service.print("AA");
    }
}



class Run{
    public static void main(String[] args){
        Service service = new Service();
        ThreadA threadA = new ThreadA(service);
        threadA.setName("A");
        threadA.start();
        ThreadB threadB = new ThreadB(service);
        threadB.setName("B");
        threadB.start();
    }
}

因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象,而改用其它

4.解决异步死循环



class RunThread extends Thread{
    private  boolean isRunning = true;
    public boolean isRunning(){
        return isRunning;
    }
    public void setRunning(boolean isRunning){
        this.isRunning = isRunning;
    }

    public void run(){
        System.out.println("进入了run");
        while(isRunning == true){

        }
        System.out.println("线程被终止了");
    }

}
public class Run {
    public static void main(String[] args){
        try{
            RunThread thread = new RunThread();
            thread.start();
            Thread.sleep(1000);
            thread.setRunning(false);
            System.out.println("已经赋值false");
        }catch(InterruptedException e){

        }
    }
}

这里会出现死循环,why?我不是已经给isRunning=false了吗?在启动RunThread线程时,private boolean isRunning=true保存在公共堆栈及线程私有堆栈中。在JVM被设置为-server模式时为了线程运行效率,线程一直在私有堆栈中取得isRunning的值true.而代码thread.setRunning(false)虽然被执行,更新的却是公共堆栈中的isRunning的值。

这里可以给变量加一个volatitle关键字,强制从公共内存中读取变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值