多用户 java并发同步_并发同步知多少

找工作的时候是否经常看到要求有高并发,分布式系统的开发设计经验,或者高并发,分布式系统的开发设计经验者优先等字样,这时候情不自禁的搜索一下什么是并发,多少算高并发,再思索一下自己的经历哪些是符合这个要求的?那么什么是并发,开发中的并发是怎么处理的,简单了解一下吧。

在介绍并发之前我们先了解一下串行和并行:

热闹的景点,买票人很多,这时只有一个窗口售票,大家排队依次买票就可以理解为串行。

排队人太多了,旁边又加开了几个窗口,多人在不同的窗口同时买票可以理解为并行。

如果只能开一个窗口,这时好多着急的人围上来,有问价格的,有掏钱的,又有取票的,在这个过程中售票员在同时应对多个买票人,可以理解为并发。

我们经常在计算机上一边听歌一边写文档(或者处理其他的事情),这就是一种并发行为,表面看两个程序是同时进行,为什么不是并行呢?计算机只有一个CPU所以只能支持一个线程运行。有人拍砖说:我家里计算机是多核CPU可以同时支持多个线程运行,确实是这样,为此我也特地去百度了一下有如下几点认知:

1、虽然是多核CPU但是,系统总线,内存是共用的,在加载内存数据时仍然需要串行访问。

2、目前的程序设计语言仍然是过程型开发,没有和好的方法能自动的切割任务使并行计算。

3、操作系统在线程调度时随着内核的增加复杂性递增,目前最多支持8核

所以基于以上认知,我们在讨论并发和同步这个问题时仍然按照CPU单核来讨论。

那么计算机是如何做到一边播放歌曲一边支持文档编辑呢?操作系统会把CPU的执行时间划分微妙级别的时间片段,每一个时间片内去调度一个线程执行,多个线程不断的切换执行,因此在人类可感知的时间段(秒级)内线程是同时执行的,所以多个线程在某个时间段内的同时执行就是并发。

串行、并行和并发如下图所示:

af071b50c92e0ca6f9d7243401eed5b1.png

互联网应用基本上都是支持多用户多请求同时访问服务器端的,所以互联网应用都是支持并发的,那么高并发的主要困难是什么呢?操作系统会给每个线程分配独立的内存空间和时间片,所以线程间是隔离的。但是如果线程访问线程外的内存空间,文件系统,输入输出设备,数据库或者其他存储设备时就会发生资源竞争,共享资源的访问必须串行,保证串行访问资源的机制就是同步,JAVA中经常使用的同步机制有synchronized关键字,java.util.concurrent.locks.Lock系列类。

同步的场景有以下几种:

1、线程获取同步锁,获取失败则阻塞等待

3a4b0d947055b18a0041583d3e764ff1.png

适用场景:

a、同步获取序列号生成器,当有其他线程获取序列号时,其他线程等待

java代码实例:

[code lang=”java”]

public class SynchronizedProcessor implements Processor {

/* (non-Javadoc)

* @see com.sunhaojie.test.thread.Processor#process(java.lang.String)

*/

public void process(String name) {

System.out.println(String.format("%s开始处理,当前时间是%d", name,

System.currentTimeMillis()));

synchronized (this) {

System.out.println(String.format("%s获得锁%s", name,

this.toString()));

try {

System.out.println(String.format("%s开始sleep", name));

Thread.sleep(1000);

System.out.println(String.format("%s结束sleep", name));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(String.format("%s释放锁%s", name,

this.toString()));

System.out.println(String.format("%s结束处理,当前时间是%d", name,

System.currentTimeMillis()));

}

}

[/code]

2、线程获取同步锁,获取失败结束

08a2dc09080537b6184748b3ad231612.png

适用场景:

a、定时任务,前一个处理线程未完成时,新线程不能获取锁则直接结束

java代码示例:

[code lang=”java”]

public class LockFailCloseProcessor implements Processor {

private static Lock lock = new ReentrantLock();

/* (non-Javadoc)

* @see com.sunhaojie.test.thread.Processor#process(java.lang.String)

*/

public void process(String name) {

System.out.println(String.format("%s开始处理,当前时间是%d", name,

System.currentTimeMillis()));

if (lock.tryLock()) {

System.out.println(String.format("%s获得锁%s", name,

this.toString()));

try {

System.out.println(String.format("%s开始sleep", name));

Thread.sleep(1000);

System.out.println(String.format("%s结束sleep", name));

} catch (InterruptedException e) {

e.printStackTrace();

}

lock.unlock();

System.out.println(String.format("%s释放锁%s", name,

this.toString()));

} else {

System.out.println(String.format("%s没有获得锁直接退出",

name));

}

System.out.println(String.format("%s结束处理,当前时间是%d", name,

System.currentTimeMillis()));

}

}

[/code]

3、线程获取同步锁后,因为其他资源不满足暂时释放同步锁,等待唤醒

b840a729d1e061a7fce0cb0e6b46002d.png

适用场景:

a、即使通讯中,发送者获取同步锁发现队列写满时,释放锁等待接收者读取数据

java代码示例:

[code lang=”java”]

public class SynchronizedWaitWriteProcessor implements Processor {

/**

* 是否可读标记,false:不可读,可写 true:可读,不可写

*/

public static int maxSize = 5;

public static List content = new ArrayList();

/* (non-Javadoc)

* @see com.sunhaojie.test.thread.Processor#process(java.lang.String)

*/

public void process(String name) {

System.out.println(String.format("%s开始处理,当前时间是%d", name,

System.currentTimeMillis()));

synchronized (content) {

System.out.println(String.format("%s获得锁%s", name,

this.toString()));

try {

if (content.size() == maxSize) {

System.out.println(

String.format("%s临时释放锁%s", name, this.toString()));

content.wait();

}

System.out.println(

String.format("%s开始写入信息", name));

Random random = new Random();

for (int i = 0; i < maxSize; i++) {

content.add(

String.format("写入信息%d", random.nextInt(1000)));

}

System.out.println(

String.format("%s结束写入信息", name));

} catch (InterruptedException e) {

e.printStackTrace();

}

content.notify();

}

System.out.println(String.format("%s释放锁%s", name,

this.toString()));

System.out.println(String.format("%s结束处理,当前时间是%d", name,

System.currentTimeMillis()));

}

}

[/code]

4、线程获取同步锁后,因为其他资源不满足结束线程

适用场景:

6f390991adbcc846d5f8b80a36273dd5.png

a、即使通讯中,接收者获取同步锁发现队列无数据时,释放锁结束线程

java代码示例:

[code lang=”java”]

public class SynchronizedWaitReadProcessor implements Processor {

/* (non-Javadoc)

* @see com.sunhaojie.test.thread.Processor#process(java.lang.String)

*/

public void process(String name) {

System.out.println(String.format("%s开始处理,当前时间是%d", name,

System.currentTimeMillis()));

synchronized (SynchronizedWaitWriteProcessor.content) {

System.out.println(String.format("%s获得锁%s", name,

this.toString()));

if (SynchronizedWaitWriteProcessor.content.size()

!= 0) {

System.out.println(

String.format("%s开始读出信息", name));

for (int i = 0;

i < SynchronizedWaitWriteProcessor.content.size(); i++) {

System.out.println("读出信息:" + SynchronizedWaitWriteProcessor.content.get(i));

}

System.out.println(

String.format("%s结束读出信息", name));

}

SynchronizedWaitWriteProcessor.content.notify();

}

System.out.println(String.format("%s释放锁%s", name,

this.toString()));

System.out.println(String.format("%s结束处理,当前时间是%d", name,

System.currentTimeMillis()));

}

}

[/code]

最后送上运行以上程序的main方法和Processor 接口类:

[code lang=”java”]

public interface Processor {

public void process(String name);

}

public class ThreadTest {

public static void main(String[] args) throws InterruptedException {

//测试SynchronizedProcessor

// Processor processor = new SynchronizedProcessor();

// for (int i = 0; i < 10; i++) {

// ProcessorThread threadProcessor =

new ProcessorThread("name" + i, processor);

// threadProcessor.start();

// }

//测试LockProcessor

// Processor processor = new LockProcessor();

// for (int i = 0; i < 10; i++) {

// ProcessorThread threadProcessor =

new ProcessorThread("name" + i, processor);

// threadProcessor.start();

// }

// Processor processor = new LockFailCloseProcessor();

// for (int i = 0; i < 10; i++) {

// ProcessorThread threadProcessor =

new ProcessorThread("name" + i,

// processor);

// threadProcessor.start();

// }

Processor readProcessor = new SynchronizedWaitReadProcessor();

ProcessorThread readThreadProcessor =

new ProcessorThread("read", readProcessor);

readThreadProcessor.start();

Processor writeProcessor = new SynchronizedWaitWriteProcessor();

ProcessorThread writeThreadProcessor =

new ProcessorThread("write", writeProcessor);

writeThreadProcessor.start();

Thread.sleep(100);

ProcessorThread read2ThreadProcessor =

new ProcessorThread("read2", readProcessor);

read2ThreadProcessor.start();

}

}

public class ProcessorThread extends Thread {

private String name;

private Processor processor;

public ProcessorThread(String name, Processor processor) {

this.name = name;

this.processor = processor;

}

public void run() {

processor.process(name);

}

}

[/code]

多线程可以大大提高性能,但是多线程的同步又增加了应用的复杂性,是否能平衡多线程的性能和复杂性是是否有高并发经验的要求。

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

weixin_39763953

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值