Java之多线程同步基础

java学习的道路上呢总有一些麻烦的东西需要花费一些时间去理解,比如个人认为不好搞的多线程.

线程是并列运行的

因为是并列运行,所以有时候会发生资源抢占,从而导致参数变化;

比如酱紫

package seer.线程;

public class SumArray {
    private int sum;

    //在这个地方sumArry()没有被同步    没有加sync...
    public int sumArray(int[] sums) {
        sum = 0;  //重置 初始化sum
        for (int i = 0; i < sums.length; i++) {
            sum += sums[i];
            try {
                Thread.sleep(10);       //发生任务切换时,有意允许切换的发生(如果加了synchronized就绝对不可能发生了.)
            } catch (InterruptedException e) {
                System.out.println("线程中断");
                e.printStackTrace();
            }
        }
        return sum;
    }
}
//===========================================================================================================

class MyThread implements Runnable {
    Thread thrd;
    static SumArray sa = new SumArray();
    int[] a;
    int answer;

    //构造一个线程
    public MyThread(String name, int[] nums) {
        thrd = new Thread(this, name);
        a = nums;
    }

    //创建一个工厂方法用来创建和启动线程
    public static MyThread createAndStart(String name, int[] nums) {
        MyThread myThrd = new MyThread(name, nums);
        myThrd.thrd.start();
        return myThrd;
    }

    @Override
    public void run() {
        int sum;
        System.out.println(thrd.getName() + "启动");
        //这里,在sa对象上对sumArray的调用进行同步
//        synchronized (sa) {
            answer = sa.sumArray(a);
            System.out.println(thrd.getName() + "计算的结果是:" + answer);
//        }
        System.out.println(thrd.getName()+"结束");
    }
}

//===========================================================================================================
//创建一个拥有main函数的类
class Sync{
    public static void main(String[] args) {
        int[] arr = {2, 3, 2, 3, 2};
        MyThread myt = MyThread.createAndStart("线程1", arr);
        MyThread myt1 = MyThread.createAndStart("线程2", arr);

    }
}

线程2启动
线程1启动
线程1计算的结果是:22
线程2计算的结果是:22
线程1结束
线程2结束

//ps 结果是22 原因是因为有一个sleep,这样才能更客观的发现两个线程的区别

创建了两个线程,两个线程不分先后的执行一个方法,由于线程的并行特性,会发生两个线程同时进入一个方法的情况, 这时候就会可能会导致数据操作次数改变,从而直接影响结果.

有两个方法:

  方法1: 

    在sumArray()方法上加synchronized关键字,加上这个关键字后的sumArray()学名叫做"同步方法"

 public synchronized int sumArray(int[] sums) {
        sum = 0;  //重置 / 初始化sum
        for (int i = 0; i < sums.length; i++) {
            sum += sums[i];
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                System.out.println("线程中断");
                e.printStackTrace();
            }
        }
        return sum;
    }

  加上synchronized  ,不管在什么样的线程情况下,可以保证每一次只能由一个线程进入这个方法,其他线程排队等待,直到当前线程执行完毕才可以进入.

    方法2

    使用同步语句

   
 static SumArray sa = new SumArray();
public void run() {
        int sum;
        System.out.println(thrd.getName() + "启动");

       synchronized (sa) {//这一段
            answer = sa.sumArray(a);
            System.out.println(thrd.getName() + "计算的结果是:" + answer);
       }
        System.out.println(thrd.getName()+"结束");
    }

    同步语句的基本格式:

      synchronized(ref){

        //方法体

      }

     这里的ref是被同步对象的引用,上文代码中就直接引用的一个普通对象

  两种方法都可以实现方法的同步阻止多线程的环境下造成数据紊乱的情况

  那么同步方法和同步语句的区别在哪呢?

  虽然同步方法时实现同步的一种简单有效的方法,但这方法并不适用于所有情况,

  例如:可能需要对某些不被synchronized修改的方法进行同步.在想使用有第三方创建的类,而无法访问源代码时就会出现这样的情况.

  这个时候使用同步代码块

  各有所需,两种用法,作用相同.

  

原文地址:https://www.cnblogs.com/lyuweigh/p/9575490.html

时间: 2024-10-29 00:15:03

Java之多线程同步基础的相关文章

Java之------多线程(从基础到加强及交互线程)

一.基础篇: 1.线程的定义 线程(thread)是操作系统进程中能够独立执行的实体(控制流),是处理器调度和分派的基本单位. 2.线程的属性 并发性,共享性,动态性,结构性 3.线程的状态 4.线程的调度 ★主要是通过实现Runnable接口和继承Thread类来实现线程的调度和操作 a.Runnable接口(里面就一个run方法,只要通过重写run方法就可以实现自己想要的线程功能) [java] view plain copy public interface Runnable { publ

【53】java的多线程同步剖析

synchronized关键字介绍: synchronized锁定的是对象,这个很重要 例子: class Sync { public synchronized void test() { System.out.println("test开始.."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test结束..&

Java 复习 —— 多线程同步

1.问题引出 在多线程环境中,可能有多个线程同时访问一个有限的资源(资源共享),为了避免资源访问.操作混乱,所以出现了锁的机制!合理控制资源的操作(读与写)权限. 2.了解几个概念 1)获取CPU资源:线程想要执行必须得到CPU资源,这是一个必要条件!然而资源的调度是操作系统根据线程的优先级.线程资源的使用等因素来确定的.不需要深究,只要知道线程想要运行必须要获取到CPU资源,这是一个门槛.我们总是纠结Thread 的 sleep.yield.start 之后到底什么时候运行,其实就是CPU资源

C#中的多线程 - 同步基础

原文:http://www.albahari.com/threading/part2.aspx 1同步概要 在第 1 部分:基础知识中,我们描述了如何在线程上启动任务.配置线程以及双向传递数据.同时也说明了局部变量对于线程来说是私有的,以及引用是如何在线程之间共享,允许其通过公共字段进行通信. 下一步是同步(synchronization):为期望的结果协调线程的行为.当多个线程访问同一个数据时,同步尤其重要,但是这是一件非常容易搞砸的事情. 同步构造可以分为以下四类: 简单的阻塞方法 这些方法

C#中的多线程 - 同步基础 z

原文:http://www.albahari.com/threading/part2.aspx 专题:C#中的多线程 1同步概要Permalink 在第 1 部分:基础知识中,我们描述了如何在线程上启动任务.配置线程以及双向传递数据.同时也说明了局部变量对于线程来说是私有的,以及引用是如何在线程之间共享,允许其通过公共字段进行通信. 下一步是同步(synchronization):为期望的结果协调线程的行为.当多个线程访问同一个数据时,同步尤其重要,但是这是一件非常容易搞砸的事情. 同步构造可以

java的多线程:线程基础

1.线程与进程区别 每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的上下文.所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务.通常由操作系统负责多个线程的调度和执行. 使用线程可以把占据时间长的程序中的任务放到后台去处理,程序的运行速度可能加快,在一些等待的任务实现上如用户输入.文件读写和网络收发数据等,线程就比较有用了.在这种情况下可以释放一些珍贵的资源如内存占用等等. 如果有

多线程同步基础

实现方式和继承方式的区别: 实现方式好处避免了但继承的局限性(不能继承其他类,只能继承Thread类) 定义线程时,建议使用实现方式. 两种方式区别: 继承Thread:线程代码存放Thread子类的run方法中 实现Runnable:线程代码存放接口子类的run方法中 同步的前提:1,必须要有两个或者两个以上的线程.2,必须是多个线程使用同一个锁(同一个对象). 必须保证同步中只能有一个线程在运行. 如何判断程序是否有安全问题:1,明确哪些代码是多线程运行代码.2,明确共享数据.3,明确多线程

[Java][Android] 多线程同步-主线程等待全部子线程完毕案例

有时候我们会遇到这种问题:做一个大的事情能够被分解为做一系列相似的小的事情,而小的事情无非就是參数上有可能不同样而已! 此时,假设不使用线程,我们势必会浪费许多的时间来完毕整个大的事情.而使用线程的话将会存在这种问题: 主线程启动全部子线程并发运行后主线程就直接返回了,导致外部函数判读整个大的事情完毕了,可是实际上并没有完毕! 针对以上情况我想我会採用多线程方式运行同一时候解决主线程等待子线程的问题.如图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ

【java】多线程同步生产者消费者问题

1 package 多线程; 2 class Producer implements Runnable{ 3 private Data data; 4 public Producer(Data data){ 5 this.data=data; 6 } 7 @Override 8 public synchronized void run() { 9 for(int i=0;i<50;i++){ 10 if(i%2==0){ 11 this.data.setTitle("饼干");