线程

学习笔记6:synchronized关键字-->线程同步

蹲街弑〆低调 提交于 2020-02-29 13:51:38
为什么要使用关键字synchronized? java程序中可以存在多个线程,但是当多个线程操作同一资源时候,可能会导致数据不一致。 区分synchronized方法与synchronized块: synchronized方法 是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法; ‍ ‍ ‍ synchronized块 ‍ ‍ 则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的其他代码是可以被多个线程同时访问到的。 ‍ 线程同步? 所谓线程同步就是若干个线程都需要使用一个synchronized(同步)修饰的方法,即程序中的若干个线程都需要使用一个方法,而这个方法用synchronized给予修饰,那么多个线程调用该方法时候必须遵守同步机制: 当一个线程A使用synchronized方法时,其他线程想使用这个synchronized方法就必须等待,直至先后才能A使用完毕。即对于synchronized修饰的方法,一次只允许一个线程访问,其他线程只能等待。 2.1 首先看看synchronized方法: public synchronized void saveOrTake(int amount){ // 这里是同步方法 } public void saveOrTake(int amount){

Java多线程-线程状态

北战南征 提交于 2020-02-29 12:41:15
线程状态 6个状态定义:java.lang.Thread.State New: 尚未启动的线程的线程状态。 Runnable: 可运行线程的线程状态,等待CPU调度。 Blocked: 线程阻塞等待监视器锁定的线程状态。处于synchronized同步代码块或方法中被阻塞。 Waiting: 等待线程的线程状态。下列不带超时的方式:Object.wait、Thread.join、LockSupport.park Timed Waiting: 具有指定等待时间的等待线程的线程状态。下列超时的方式:Thread.sleep、Object.wait、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil 常见线程状态切换 新建->运行->终止 Thread thread1 = new Thread(new Runnable() { @Override public void run() { System.out.println("thread1当前状态:" + Thread.currentThread().getState().toString()); System.out.println("thread1 执行了"); } }); System.out.println("没调用start方法,thread1当前状态:" +

Nginx知识汇总(一)

╄→尐↘猪︶ㄣ 提交于 2020-02-29 12:31:53
一、选择Nginx作为中间件的原因: 1、IO多路复用epoll 多个文件描述符的I/O操作都能在一个线程内并发交替地顺序完成,这里的复用,指的是复用同一个线程。 仍然还是一个线程来处理多个IO流请求,但与单线程的方式不同,其由IO流来主动上报,上报了,那么这个线程就去处理,其他线程等待 I/O多路复用就通过一种机制,可以监视多个文件描述符,一旦某个文件描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。 同步IO和异步IO select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的 而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。 epoll实现 ①epoll采用事件驱动模型,每当FD就绪,采用系统的回调函数将fd放入就绪的列表,这样就知道队列中的哪个线程完成了,效率更高(不需要再进行轮询了) ②最大连接无限制 2、轻量级(功能模块少,代码模块化) 3、CPU亲和(affinity) cpu亲和是一种把cpu核心和Nginx工作进程绑定方式,把每个worker进程固定在一个cpu上执行,减少切换cpu的cahce miss(cpu高速缓存),获得更好的性能 4.nginx的sendfile 请求一个文件要经过操作系统的内核空间-

JUC学习之Lock同步锁

夙愿已清 提交于 2020-02-29 11:25:32
一、简介 引出Lock同步锁之前,先了解一下synchronized同步的一些缺陷: 如果一段代码被synchronized锁住,那么当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁。如果某个时刻获得锁的线程发生阻塞现象,那么这把锁会被它一直持有,而其他线程永远无法获取锁,正常来说,不能让其他线程永远在那里等待。 使用Lock锁的话,提供了一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断); 使用Lock锁的话,通过tryLock()方法可以尝试获取锁,这就知道线程有没有成功获取到锁; 基于上面Lock的两大优势,我们今天总结一下Lock同步锁相关的知识。 Lock是一个接口,源码如下: public interface Lock { //获取锁,如果锁已被其他线程获取,则进行等待。 void lock(); //当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态 void lockInterruptibly() throws InterruptedException; //尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false boolean tryLock(); //指定时间内尝试获取锁,在拿不到锁时会等待一定的时间

pthread_create

妖精的绣舞 提交于 2020-02-29 11:22:16
1函数简介 头文件 #include<pthread.h> 函数声明 intpthread_create(pthread_t*tidp,constpthread_attr_t*attr, (void*)(*start_rtn)(void*),void*arg); 返回值 若线程创建成功,则返回0。若线程创建失败,则返回出错编号,并且*thread中的内容是未定义的。[1] 返回成功时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于指定各种不同的线程属性。 新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函 数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。 linux下用C语言开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。 由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时, 才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的 指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译 器能通过作出 restrict

关于String StringBuffer StringBuilder

余生长醉 提交于 2020-02-29 11:09:46
0. String对象的创建 1、关于类对象的创建,很普通的一种方式就是利用构造器,String类也不例外:String s=new String("Hello world"); 问题是参数"Hello world"是什么东西,也是字符串对象吗?莫非用字符串对象创建一个字符串对象? 2、当然,String类对象还有一种大家都很喜欢的创建方式:String s="Hello world"; 但是有点怪呀,怎么与基本数据类型的赋值操作(int i=1)很像呀? 在开始解释这些问题之前,我们先引入一些必要的知识: 1. Java class文件结构 和常量池 我们都知道,Java程序要运行,首先需要编译器将源代码文件编译成字节码文件(也就是.class文件)。然后在由JVM解释执行。 class文件是8位字节的二进制流 。这些二进制流的涵义由一些紧凑的有意义的项 组成。比如class字节流中最开始的4个字节组成的项叫做魔数 (magic),其意义在于分辨class文件(值为0xCAFEBABE)与非class文件。class字节流大致结构如下图左侧。 其中,在class文件中有一个非常重要的项—— 常量池 。这个常量池专门放置源代码中的符号信息(并且不同的符号信息放置在不同标志的常量表中)。如上图右侧是HelloWorld代码中的常量表(HelloWorld代码如下)

Java基础 —— 多线程与并发

喜夏-厌秋 提交于 2020-02-29 11:03:38
进程与线程的关系 基本概念 进程 :是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是操作系统进行资源分配和调度的基本单位。 线程 :是操作系统能够进行运算调度的最小单位,是操作系统独立调度和分派的基本单位。被包含于 进程 中,是 进程 的实际运作单位。 两者关系 一个 进程 可以有多个 线程 ,多个 线程 共享进程的堆和方法区资源。但每个线程有各自的程序计数器和栈区域。 程序计数器:用于记录线程当前要执行的指令地址信息的区域; 栈:用于存储线程私有的局部变量和线程调用栈祯的区域; 堆:进程中最大的一块内存区域,存放各种变量信息,为线程共享; 方法区:用于存放JVM加载的类、常量及静态变量等信息的区域,为线程共享。 两者区别 进程 具有独立的地址空间,一个进程崩溃后不会对其它进程产生影响; 线程 是一个进程中的某个执行路径,由于线程没有独立的地址空间,其死掉可能会影响到整个进程; 线程 的开销相对于 进程 而言,要更“轻量级”; 一个 进程 内的多个 线程 ,由于共享进程资源的原因,通信更快速、有效,极大提高了程序的运行效率; 线程 不能单独执行,必须依赖存在于进程中。 PS:抽象的讲,进程和线程的关系就好比工厂和工人的关系,进程是工厂而线程是工厂里的工人。 并行与并发 基本概念 并行 :当系统有一个以上CPU时,每个CPU单独执行一个线程

Java内存分配及垃圾回收

白昼怎懂夜的黑 提交于 2020-02-29 10:26:28
一:Java虚拟机数据区组成 Java虚拟机数据区有五大部分组成,分别是:方法区、堆区、虚拟机堆栈区、本地方法区、程序计数器区,这五个部分分成两组,分别是: (A)线程共享部分: 1.方法区:这个区域被各个线程共享使用,用来存储被虚拟机加载的类、常量、静态变量、即时编译后代码等信息,这个区域相对于【堆区】而言稳定很多,但仍然存在内存溢出的概率,本区会涉及到内存回收。 2.堆区:堆区是虚拟机中内存中占用最大的一部分,用来存储由各个线程运行时创建的各种非瞬时性的对象副本,因为涉及到多线程的同时使用(读取和写入),因此,这个区域是垃圾回收机制发挥主要作用的地方,也是最容易发生内存泄漏的地方,这个区域是内存管理的核心区域,内存管理的大部分功能都是围绕着这个区域的健康运行而设计的。 (B)线程独占部分: 3.虚拟机堆栈:这个区域其实就是单个线程的操作区,相当于线程这个工人的私人操作台。 4.本地方法栈:和虚拟机栈类似,只是Java虚拟机使用到的本地(非本虚拟机产生或者由其它语言产生的方法)方法提供服务的场所,类似于向其它厂商提供零件、接收其它厂商零件等等与配套厂商协作的场所。 5.程序计数器:这个区域用来记录单个线程在运行过程行号、跳转控制等等。 二、对象内存分配: 当虚拟机遇到new指令时,虚拟机会在方法区的常量池中去寻找这个类的引用标记,如果找到则进行分配内存,初始化变量等;如果没有找到

JUC学习之循环栅栏CyclicBarrier

爱⌒轻易说出口 提交于 2020-02-29 10:04:14
一、简介 前面已经简单介绍了CountDownLatch闭锁,本文的CyclicBarrier其实跟闭锁差不多,当然还是存在一些区别。 官网介绍如下: CyclicBarrier是一种同步辅助工具,允许一组线程彼此等待到达一个共同的障碍点。CyclicBarrier在包含固定大小的线程的程序中非常有用,这些线程有时必须彼此等待。这个屏障被称为循环屏障,因为它可以在等待的线程被释放后重新使用。 CyclicBarrier支持一个可选的Runnable命令,该命令在在最后一个线程到达之后,但是在释放任何线程之前执行,这个屏障动作对于在任何一方继续之前更新共享状态非常有用。 通俗理解,就是CyclicBarrier可以使一定数量的线程反复地在栅栏位置处汇集。在CyclicBarrier类的内部有一个计数器,每个线程在到达屏障点的时候都会调用await方法将自己阻塞,此时计数器会减1,当计数器减为0的时候,所有因调用await方法而被阻塞的线程将被唤醒。如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使用(栅栏可重复使用)。 二、常见API 构造方法: //创建一个新的CyclicBarrier,当给定数量的参与方(线程)正在等待它时,它将会跳闸,并且在跳闸时不会执行预定义的操作。 CyclicBarrier(int parties) /