廖雪峰Java11多线程编程-2线程同步-2synchronized方法

1.Java使用synchronized对一个方法进行加锁

class Counter{
    int count = 0;
    public synchronized void add(int n){
        count += n;
    }
    public synchronized void dec(int n){
        count -= n;
    }
    public int get(){//读取一个int类型是原子操作,不需要同步
        return count;
    }
}
class AddThread extends Thread {
    Counter counter;

    public AddThread(Counter counter) {
        this.counter = counter;
    }

    public void run() {
        for (int i = 0; i < Main.LOOP; i++) {
            counter.add(1);
        }
    }
}
class DecThread extends Thread{
    Counter counter;
    public DecThread(Counter counter){
        this.counter = counter;
    }
    public void run(){
        for(int i=0;i<Main.LOOP;i++){
            counter.dec(1);
        }
    }
}

public class Main{
    static final int LOOP=10000;
    public static void main(String[] args) throws InterruptedException{
        Counter counter  = new Counter();
        Thread t1 = new AddThread(counter);
        Thread t2 = new DecThread(counter);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(counter.get());
    }
}

2.读取方法是否需要同步?

    public int get(){ //读取一个int类型是原子操作,不用同步
        return count;
    }
    public synchronized int[] get(){
        int[] result = new int[2];
        result[0] = this.value[0];
        result[1] = this.value[1];//读取万result[0],如果其他线程改变了result[1]的值,会导致读取的结果不一致。
        return result;
    }

所以,为了保险起见,读取方法通常也要同步。

3.线程安全与非线程安全

如果一个类被设计为允许多线程正确访问:

  • 这个类就是“线程安全”的(thread-safe),如java.lang.StringBuffer,其方法基本是synchronized

    线程安全的类:
  • 不变类:String,Integer,LocalDate。一旦创建,实际内部的成员变量无法改变,所以多线程只能读,不能写,不需要同步,就是安全的。
  • 没有成员变量的类:Math,这些工具类只提供了静态方法,没有成员变量。
  • 正确使用synchronized的类:StringBuffer

非线程安全的类:

  • 不能在多线程中共享实例并修改:ArrayList
  • 可以在多线程中以只读方式共享

4.总结:

  • 用synchronized修饰方法可以把整个方法变为同步代码块
  • synchronized方法加锁对象是this
  • 通过合理的设计和数据封装可以让一个类变为线程安全
  • 一个类没有特殊说明,默认不是thread-safe
  • 多线程能否访问某个非线程安全的实例,需要具体问题具体分析

原文地址:https://www.cnblogs.com/csj2018/p/11001483.html

时间: 2024-11-05 20:27:36

廖雪峰Java11多线程编程-2线程同步-2synchronized方法的相关文章

廖雪峰Java11多线程编程-4线程工具类-1ThreadLocal

class User{ String name; int level; public User(String name, int level){ this.name = name; this.level = level; } } class UserContext implements AutoCloseable{ static final ThreadLocal<User> context = new ThreadLocal<>(); public static User get

廖雪峰Java11多线程编程-3高级concurrent包-1ReentrantLock

线程同步: 是因为多线程读写竞争资源需要同步 Java语言提供了synchronized/wait/notify 编写多线程同步很困难 所以Java提供了java.util.concurrent包: 更高级的同步功能 简化多线程程序的编写 JDK>= 1.5 java.util.locks.ReetrantLock用于替代synchronized加锁 ```#java synchronized(lockObj){ n = n + 1; } final Lock lock = new Reetra

廖雪峰Java11多线程编程-3高级concurrent包-5Atomic

Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int incrementAndGet() int get() int compareAndGet() Atomic类可以实现: 无锁(lock-free)实现的线程安全(thread-safe)访问 原理:CAS(Compare and Set)如果AtomicInteger实例的值是prev,就替换为next,返回

Linux程序设计学习笔记----多线程编程之线程同步之条件变量

转载请注明出处:http://blog.csdn.net/suool/article/details/38582521. 基本概念与原理 互斥锁能够解决资源的互斥访问,但是在某些情况下,互斥并不能解决问题,比如两个线程需 要互斥的处理各自的操作,但是一个线程的操作仅仅存在一种条件成立的情况下执行,一旦错过不可再重现,由于线程间相互争夺cpu资源,因此在条件成立的时候,该线程不一定争夺到cpu而错过,导致永远得不到执行..... 因此需要某个机制来解决此问题,更重要的是,线程仅仅只有一种情况需要执

.NET面试题解析(07)-多线程编程与线程同步

系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实是很多的,比如多线程编程.线程上下文.异步编程.线程同步构造.GUI的跨线程访问等等,本文只是从常见面试题的角度(也是开发过程中常用)去深入浅出线程相关的知识.如果想要系统的学习多线程,没有捷径的,也不要偷懒,还是去看专业书籍的比较好. 常见面试题目: 1. 描述线程与进程的区别? 2. 为什么GUI不支持跨线程访问控件?一般如何解决这个问题? 3. 简述后台线程和前台线程的区别? 4. 说说常

C# 多线程编程第二步——线程同步与线程安全

上一篇博客学习了如何简单的使用多线程.其实普通的多线程确实很简单,但是一个安全的高效的多线程却不那么简单.所以很多时候不正确的使用多线程反倒会影响程序的性能. 下面先看一个例子 : class Program { static int num = 1; static void Main(string[] args) { Stopwatch stopWatch = new Stopwatch(); //开始计时 stopWatch.Start(); ThreadStart threadStart

Delphi中线程类TThread实现多线程编程(线程同步技术、Synchronize、WaitFor……)

接着上文介绍TThread. 现在开始说明 Synchronize和WaitFor 但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区 事件(Event)与Delphi中的事件有所不同.从本质上讲,Event其实就相当于一个全局的布尔变量.它有两个赋值操作:Set和ReSet,相当于把它设置为 True或False.而检查它的值是通过WaitFor操作进行.对应在Windows平台上,是三个API函数:SetEvent.ResetEvent.WaitForSignalObje

iOS多线程编程:线程同步总结 NSCondtion

1:原子操作 - OSAtomic系列函数 iOS平台下的原子操作函数都以OSAtomic开头,使用时需要包含头文件<libkern/OSBase.h>.不同线程如果通过原子操作函数对同一变量进行操作,可以保证一个线程的操作不会影响到其他线程内对此变量的操作,因为这些操作都是原子式的.因为原子操作只能对内置类型进行操作,所以原子操作能够同步的线程只能位于同一个进程的地址空间内. 2:锁 - NSLock系列对象 iOS平台下的锁对象为NSLock对象,进入锁通过调用lock函数,解锁调用unl

七. 多线程编程8.线程同步

当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一刻仅被一个线程占用.达到此目的的过程叫做同步(synchronization).像你所看到的,Java为此提供了独特的,语言水平上的支持. 同步的关键是管程(也叫信号量semaphore)的概念.管程是一个互斥独占锁定的对象,或称互斥体(mutex).在给定的时间,仅有一个线程可以获得管程.当一个线程需要锁定,它必须进入管程.所有其他的试图进入已经锁定的管程的线程必须挂起直到第一个线程退出管程.这些其他的线程被称为等待管程.一个