多线程编程核心技术-对象及变量的并发访问-synchronize同步方法(2)(上)

简介: 多线程编程核心技术-对象及变量的并发访问-synchronize同步方法(2)(上)

对象及变量的并发访问之synchronize同步方法:


1)方法内的变量为线程安全

1dc618a0ed9580ce8bfa6facb208c08f.png

例子:


public class HasSelfPrivateNum {
    public void addI(String username){
        try{
            int num = 0;
            if(username.equals("a")){
                num = 100;
                System.out.println("a set over");
                Thread.sleep(2000);
            }else{
                num = 200;
                System.out.println("b set over");
            }
            System.out.println(username + " num="+ num);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}


public class ThreadA extends  Thread {
    private HasSelfPrivateNum numRef;
    public ThreadA(HasSelfPrivateNum numRef) {
        super();
        this.numRef = numRef;
    }
    @Override
    public void run() {
        super.run();
        numRef.addI("a");
    }
}


public class ThreadB extends Thread {
    private HasSelfPrivateNum numRef;
    public ThreadB(HasSelfPrivateNum numRef) {
        super();
        this.numRef = numRef;
    }
    @Override
    public void run() {
        super.run();
        numRef.addI("b");
    }
}


public class Run {
    public static void main(String[] args) {
        HasSelfPrivateNum selfPrivateNum = new HasSelfPrivateNum();
        ThreadA threadA = new ThreadA(selfPrivateNum);
        threadA.start();
        ThreadB threadB = new ThreadB(selfPrivateNum);
        threadB.start();
    }
}


运行结果:

1dc618a0ed9580ce8bfa6facb208c08f.png

5d4c6812c8535adbb050f4ddf2e1bce8.png


2)实例变量非线程安全


上面的例子,讲num从私用变量,改成成员变量。再次运行结果:


public class HasSelfPrivateNum {
    private  int num = 0;
    public void addI(String username){
        try{
            if(username.equals("a")){
                num = 100;
                System.out.println("a set over");
                Thread.sleep(2000);
            }else{
                num = 200;
                System.out.println("b set over");
            }
            System.out.println(username + " num="+ num);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}


运行结果:

1dc618a0ed9580ce8bfa6facb208c08f.png

5d4c6812c8535adbb050f4ddf2e1bce8.png


解决非线程安全


public class HasSelfPrivateNum {
    private  int num = 0;
    synchronized public void addI(String username){
        try{
            if(username.equals("a")){
                num = 100;
                System.out.println("a set over");
                Thread.sleep(2000);
            }else{
                num = 200;
                System.out.println("b set over");
            }
            System.out.println(username + " num="+ num);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}


再次运行结果:

1dc618a0ed9580ce8bfa6facb208c08f.png

5d4c6812c8535adbb050f4ddf2e1bce8.png


3)多个对象多个锁


接着上面的实验,改动下,Run类,声明2个对象


public class Run {
    public static void main(String[] args) {
        HasSelfPrivateNum selfPrivateNum1 = new HasSelfPrivateNum();
        HasSelfPrivateNum selfPrivateNum2 = new HasSelfPrivateNum();
        ThreadA threadA = new ThreadA(selfPrivateNum1);
        threadA.start();
        ThreadB threadB = new ThreadB(selfPrivateNum2);
        threadB.start();
    }
}


看下效果:

46a9d80a6e05e4e3b19d57a0ee70bcdf.png

66ba272a0bfc97be54a5fa679e3d5482.png



4)synchronize方法与锁对象


实验1


public class MyObject {
    public void methodA(){
        try{
            System.out.println("begin methodA threadName=" + Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}


public class ThreadA extends Thread{
   private MyObject object;
    public ThreadA(MyObject object) {
        this.object = object;
    }
    @Override
    public void run() {
        super.run();
        object.methodA();
    }
}


public class ThreadB extends Thread {
    private MyObject object;
    public ThreadB(MyObject object) {
        this.object = object;
    }
    @Override
    public void run() {
        super.run();
        object.methodA();
    }
}


public class Run {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        ThreadA thread1 = new ThreadA(myObject);
        thread1.setName("A");
        ThreadB thread2 = new ThreadB(myObject);
        thread1.start();
        thread2.setName("B");
        thread2.start();
    }
}

1dc618a0ed9580ce8bfa6facb208c08f.png

结果显示:2个线程一同进入了methodA方法。


实验2


改进上面的实验,加个synchronize关键字


synchronized public class MyObject {
    public void methodA(){
        try{
            System.out.println("begin methodA threadName=" + Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

1dc618a0ed9580ce8bfa6facb208c08f.png

结果: 排队进入方法

5d4c6812c8535adbb050f4ddf2e1bce8.png


实验3:


继续改进myObject类,再加一个非同步方法


public class MyObject {
    synchronized  public void methodA(){
        try{
            System.out.println("begin methodA threadName=" + Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    public void methodB(){
        try {
            System.out.println("begin methodB threadName=" +
                                Thread.currentThread().getName() + "begin time=" +
                                System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("end");
        }catch (Exception e){
        }
    }
}


同样,让ThreadB调用非同步方法B


public class ThreadB extends Thread {
    private MyObject object;
    public ThreadB(MyObject object) {
        this.object = object;
    }
    @Override
    public void run() {
        super.run();
        object.methodB();
    }
}


1dc618a0ed9580ce8bfa6facb208c08f.png

5d4c6812c8535adbb050f4ddf2e1bce8.png

所以,methodB方法也加上synchronize关键字试试:

46a9d80a6e05e4e3b19d57a0ee70bcdf.png

可以看出来,又同步了奥!

66ba272a0bfc97be54a5fa679e3d5482.png



相关文章
|
9天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
25 2
|
9天前
|
Java
COMATE插件实现使用线程池高级并发模型简化多线程编程
本文介绍了COMATE插件的使用,该插件通过线程池实现高级并发模型,简化了多线程编程的过程,并提供了生成结果和代码参考。
|
11天前
|
Java 数据处理 调度
Java中的多线程编程:从基础到实践
本文深入探讨了Java中多线程编程的基本概念、实现方式及其在实际项目中的应用。首先,我们将了解什么是线程以及为何需要多线程编程。接着,文章将详细介绍如何在Java中创建和管理线程,包括继承Thread类、实现Runnable接口以及使用Executor框架等方法。此外,我们还将讨论线程同步和通信的问题,如互斥锁、信号量、条件变量等。最后,通过具体的示例展示了如何在实际项目中有效地利用多线程提高程序的性能和响应能力。
|
11天前
|
安全 算法 Java
Java中的多线程编程:从基础到高级应用
本文深入探讨了Java中的多线程编程,从最基础的概念入手,逐步引导读者了解并掌握多线程开发的核心技术。无论是初学者还是有一定经验的开发者,都能从中获益。通过实例和代码示例,本文详细讲解了线程的创建与管理、同步与锁机制、线程间通信以及高级并发工具等主题。此外,还讨论了多线程编程中常见的问题及其解决方案,帮助读者编写出高效、安全的多线程应用程序。
|
2月前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
65 1
|
9天前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
16天前
|
Java Spring
spring多线程实现+合理设置最大线程数和核心线程数
本文介绍了手动设置线程池时的最大线程数和核心线程数配置方法,建议根据CPU核数及程序类型(CPU密集型或IO密集型)来合理设定。对于IO密集型,核心线程数设为CPU核数的两倍;CPU密集型则设为CPU核数加一。此外,还讨论了`maxPoolSize`、`keepAliveTime`、`allowCoreThreadTimeout`和`queueCapacity`等参数的设置策略,以确保线程池高效稳定运行。
83 10
spring多线程实现+合理设置最大线程数和核心线程数
|
25天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
45 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
7天前
|
NoSQL 网络协议 Unix
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
20 1
|
10天前
|
Python
5-5|python开启多线程入口必须在main,从python线程(而不是main线程)启动pyQt线程有什么坏处?...
5-5|python开启多线程入口必须在main,从python线程(而不是main线程)启动pyQt线程有什么坏处?...