自己动手写把”锁”之---锁的作用

前序

这是一个系列文章,前边几篇比较基础,主要为了后续做准备。熟悉的朋友可以直接跳过看后续的文章。

本主题很重要,学完这个系列,你将会对Java并包有一个透彻的原理性的认识。线程池技术、阻塞队列、信号量、原子性操作等等所用的基础技术都会在这系列的文章中讲到。学完之后,大家可以自己实现一个CountDownLatch来练练手。

正文

都知道,现在处理器的核数越来越多,为充分利用其计算资源,服务端编程通常会用上多线程技术。利用多线程技术可以同时进行计算任务,从而提高的服务的并发度。

但是,当多线程对同一块内存资源进行操作时,如果不对线程进行“排队”,其结果将是混乱不堪预测额。

这里说的“排队”就是通常说的线程同步。当一个线程在操作这个资源时,后来的线程等待上一个线程操作完才能开始。

举个代码栗子:

public class TestMyLock {
    private static  List<Integer> list = new ArrayList<>();
    public static void main(String[] args){
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=0;i<10000;i++){
                    add(i);
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                print();
            }
        });
        t1.start();
        t2.start();
    }
    private static void add(int i){
        list.add(i);
    }
    private static void print(){
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

以上我们创建了两个线程:t1和t2。t1循环一万次向list里边添加数字,t2遍历list并将内容打印到控制台。

执行后得到如下错误:

原因很简单,就是两个线程同时操作list而没有进行线程同步导致的报错。我们修改下代码再来看一下。

add和print方法修改为如下:

private synchronized static void add(int i){
        list.add(i);
}
private synchronized static void print(){
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }}

我们仅仅是在add和print方法前加入了synchronized修饰词,程序便可以正常执行了。

synchronized关键字是Java内置的同步锁。两个线程会竞争对synchronized绑定的同步对象加锁,加锁失败的线程会阻塞等待加锁成功的线程执行完毕。由于add和print方法都是静态方法,这里synchronized绑定的同步对象就是TestMyLock.class。

原文地址:https://www.cnblogs.com/qingquanzi/p/8158484.html

时间: 2024-10-10 16:02:04

自己动手写把”锁”之---锁的作用的相关文章

《自己动手写框架4》:分布式锁的简单实现

分布式锁在分布式应用当中是要经常用到的,主要是解决分布式资源访问冲突的问题.  一开始考虑采用ReentrantLock来实现,但是实际上去实现的时候,是有问题的,ReentrantLock的lock和unlock要求必须是在同一线程进行,而分布式应用中,lock和unlock是两次不相关的请求,因此肯定不是同一线程,因此导致无法使用ReentrantLock. 接下来就考虑采用自己做个状态来进行锁状态的记录,结果发现总是死锁,仔细一看代码,能不锁死么. public synchronized

写文章 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底层实现浅尝辄止,但是在需要时能够知道去查什么. 首先要打消一种想法,就是一个锁只能属于一种分类.其实并不是这样,比如一个锁可以同时是悲观锁.可重入锁.公平锁.可中断锁等等,就像一个人可以是男人.医生.健身爱好者.游戏玩家,这并不矛盾.OK,国际惯例,上干货. 〇.synchronized与Lock

【自己动手写数据库】(不断更新中)

有一个大胆的想法,自己写个数据库. 1.先从最简单的建表,删除表功能写起. 2.IUD操作.Insert/Update/Delete. 3.支持索引 4.支持查询,SELECT 5.支持排序,ORDER BY 6.优化器,初步的解析功能,语义分析,语法分析 7.实现Buffer Pool功能 8.实现日志功能,在DDL,IUD等重要的操作,支持写日志. 9.支持锁机制. 10.进程模型优化,启动实例,停止实例. 11.Catalog表的支持. 12.备份恢复,崩溃恢复. 13.其它的慢慢完善.

自己动手写处理器之第一阶段(1)——计算机的简单模型、架构、指令集

将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第二篇,我尽量每周四篇 第1章 处理器与MIPS 时间开始了! --胡风 · 1949 让我们以一句诗意的话,开始本书的阅读. 时间从1971年11月15日开始,那一天,Intel发布了世界上第一款单芯片微处理器4004. 1.1 计算机的简单模型 计算机很复杂,可以听歌.看电影.上网.玩游戏,内部是怎么工作的,这个问题太可怕了,太复杂了. 计算机很简单,只有加.减.乘.除.逻辑.移位.转移.存储.加载等几类可以做的操作,太简单了.

可重入锁 &amp; 自旋锁 &amp; Java里的AtomicReference和CAS操作 &amp; Linux mutex不可重入

之前还是写过蛮多的关于锁的文章的: http://www.cnblogs.com/charlesblc/p/5994162.html <[转载]Java中的锁机制 synchronized & 偏向锁 & 轻量级锁 & 重量级锁 & 各自> http://www.cnblogs.com/charlesblc/p/5935326.html <[Todo] 乐观悲观锁,自旋互斥锁等等> http://www.cnblogs.com/charlesblc/

[转]数据库并发控制 乐观锁,悲观锁

在数据库中,并发控制有乐观锁和悲观锁之间,什么时候用乐观锁比较好什么时候用悲观锁比较好? 实际生产环境里边,如果并发量不大,完全可以使用悲观锁定的方法,这种方法使用起来非常方便和简单.但是如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以就要选择乐观锁定的方法. 悲观锁假定其他用户企图访问或者改变你正在访问.更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁.悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长

走入计算机的第三十六天(自己创建锁及锁的类型)

python thread模块 锁 同步锁 Python中的线程是操作系统的原生线程,Python虚拟机使用一个全局解释器锁(Global Interpreter Lock)来互斥线程对Python虚拟机的使用.为了支持多线程机制,一个基本的要求就是需要实现不同线程对共享资源访问的互斥,所以引入了GIL.GIL:在一个线程拥有了解释器的访问权之后,其他的所有线程都必须等待它释放解释器的访问权,即使这些线程的下一条指令并不会互相影响.在调用任何Python C API之前,要先获得GILGIL缺点

java 中的锁 -- 偏向锁、轻量级锁、重量级锁

理解锁的基础知识 如果想要透彻的理解java锁的来龙去脉,需要先了解以下基础知识. 基础知识之一:锁的类型 锁从宏观上分类,分为悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作. java中的乐观锁基本都是通过CAS操作实现的,CAS

MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)

锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一种供许多用户共享访问的资源.如何保证数据并发访问的一致性.有效性,是所有数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素.从这一角度来说,锁对于数据库而言就显得尤为重要. MySQL锁 相对于其他的数据库而言,MySQL的锁机制比较简单,最显著的特点就是不同的存储引擎支持不

MySQL 行锁 表锁机制

MySQL 表锁和行锁机制 行锁变表锁,是福还是坑?如果你不清楚MySQL加锁的原理,你会被它整的很惨!不知坑在何方?没事,我来给你们标记几个坑.遇到了可别乱踩.通过本章内容,带你学习MySQL的行锁,表锁,两种锁的优缺点,行锁变表锁的原因,以及开发中需要注意的事项.还在等啥?经验等你来拿! MySQL的存储引擎是从MyISAM到InnoDB,锁从表锁到行锁.后者的出现从某种程度上是弥补前者的不足.比如:MyISAM不支持事务,InnoDB支持事务.表锁虽然开销小,锁表快,但高并发下性能低.行锁