多线程编程核心技术-对象及变量的并发访问-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



相关文章
|
7天前
|
数据采集 存储 Java
高德地图爬虫实践:Java多线程并发处理策略
高德地图爬虫实践:Java多线程并发处理策略
|
2天前
|
Dart 前端开发 安全
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
【4月更文挑战第30天】本文探讨了Flutter中线程管理和并发编程的关键性,强调其对应用性能和用户体验的影响。Dart语言提供了`async`、`await`、`Stream`和`Future`等原生异步支持。Flutter采用事件驱动的单线程模型,通过`Isolate`实现线程隔离。实践中,可利用`async/await`、`StreamBuilder`和`Isolate`处理异步任务,同时注意线程安全和性能调优。参考文献包括Dart异步编程、Flutter线程模型和DevTools文档。
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
|
2天前
|
算法 安全
AtomicInteger使用非阻塞算法,实现并发控制多线程实现售票
AtomicInteger使用非阻塞算法,实现并发控制多线程实现售票
|
8天前
|
并行计算 算法 安全
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
|
8天前
|
监控 安全 Java
一文讲明白Java中线程与进程、并发与并行、同步与异步
一文讲明白Java中线程与进程、并发与并行、同步与异步
7 1
|
10天前
|
NoSQL
线程死循环的定位方法
线程死循环的定位方法
17 2
|
12天前
使用代理IP池实现多线程的方法
使用代理IP池实现多线程的方法
|
13天前
|
安全 Java
深入理解 Java 多线程和并发工具类
【4月更文挑战第19天】本文探讨了Java多线程和并发工具类在实现高性能应用程序中的关键作用。通过继承`Thread`或实现`Runnable`创建线程,利用`Executors`管理线程池,以及使用`Semaphore`、`CountDownLatch`和`CyclicBarrier`进行线程同步。保证线程安全、实现线程协作和性能调优(如设置线程池大小、避免不必要同步)是重要环节。理解并恰当运用这些工具能提升程序效率和可靠性。
|
2天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
2天前
|
缓存 安全 Java
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
多线程--深入探究多线程的重点,难点以及常考点线程安全问题

相关实验场景

更多