java并发包是谁编写的_java 高并发包

"

1.首先,明确两个问题,synchronized 一般不是跟AtomicXX类进行比较,更多的是跟ReentrantLock这个类进行比较,网上关于这2者的比较很多,可以自行google之。

2.问题中关于无锁跟有锁的疑问,测试代码b中的代码是有问题的,

对于方法a,synchronized代码块来说,锁被第一个进来的线程持有后,后续线程请求获取锁会被阻塞挂起,直到前面一个线程释放锁,后续的线程会恢复执行,由于锁的存在,20个请求类似于顺序执行,这一层由jvm调度对于方法b,cas操作是非阻塞的,方法中的while循环其实是一直在执行(不断尝试进行cas操作),而我们知道,死循环是会消耗cpu资源的,并发数越多,线程越多,此处的cas操作越多,必然导致cpu使用率飙升,方法b中的代码由jmeter测试的时候理论上来说应该一直由20个活跃的工作线程存在,cpu与线程模型是另外一个话题,线程数的调优是jvm一个比较高级的话题,感兴趣可以自行google之说说ReentrantLock与synchronized:通常情况下在高并发下,ReentrantLock比synchronized拥有更好的性能,而且ReentrantLock提供来一些synchronized并不提供的功能(锁超时自动放弃等),示例代码中可以减少sleep的时间,从而模拟更短停顿,更高的并发,500ms对于人来说很短,对于cpu来说基本就是天文数字了,基本用“慢如蜗牛”来形容也不为过,修改类一下示例代码:

package com.gzs.learn.springboot;

import java.util.LinkedList;

import java.util.Random;

import java.util.concurrent.atomic.AtomicReference;

import java.util.concurrent.locks.LockSupport;

import java.util.concurrent.locks.ReentrantLock;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

@Controller

@RequestMapping("/bench/")

public class BenchController {

private Random random = new Random();

private static Object[] lockObj;

private static AtomicReference[] locks;

private static ReentrantLock[] reentrantLocks;

static {

lockObj = new Object[100];

for (int i = 0; i < lockObj.length; i++) {

lockObj[i] = new Object();

}

locks = new AtomicReference[100];

for (int i = 0; i < locks.length; i++) {

locks[i] = new AtomicReference(null);

}

reentrantLocks = new ReentrantLock[100];

for (int i = 0; i < reentrantLocks.length; i++) {

reentrantLocks[i] = new ReentrantLock();

}

}

@RequestMapping("a/{id}")

@ResponseBody

public long a(@PathVariable("id") int id) throws Exception {

long start = System.currentTimeMillis();

int index = id % 100;

long inner = 0;

synchronized (lockObj[index]) {

inner = test();

}

long result = System.currentTimeMillis() - start;

System.out.println("all: " + result + " inner: " + inner);

return result;

}

@RequestMapping("b/{id}")

@ResponseBody

public long b(@PathVariable("id") int id) throws Exception {

long start = System.currentTimeMillis();

id = id % 100;

AtomicReference lock = locks[id];

int b = 0;

while (!lock.compareAndSet(null, id)) {

b = 1 + 1;

}

long inner = test();

boolean flag = lock.compareAndSet(id, null);

long result = System.currentTimeMillis() - start;

System.out.println("all: " + result + " inner: " + inner + " flag:" + flag);

System.out.println(b);

return result;

}

@RequestMapping("c/{id}")

@ResponseBody

public long c(@PathVariable("id") int id) throws Exception {

long start = System.currentTimeMillis();

id = id % 100;

ReentrantLock lock = reentrantLocks[id];

lock.lock();

long inner = test();

lock.unlock();

long result = System.currentTimeMillis() - start;

System.out.println("all: " + result + " inner: " + inner);

return result;

}

public long test() throws Exception {

long innerstart = System.currentTimeMillis();

Thread.sleep(0, 100);

// Thread.sleep(500);

System.out.println(System.currentTimeMillis() - innerstart);

return System.currentTimeMillis() - innerstart;

}

}

方法c是用ReentrantLock实现的,绝大多少情况下ReentrantLock比synchronized高效juc(java.util.concurrent)中的核心类Aqs(AbstractQueuedSynchronizer)是一个基于队列的 并发包,默认线程在锁竞争(自旋)超过1000纳秒的时候会被park(挂起操作),从而减少cpu频繁的线程切换,可以尝试调整方法c中的sleep的时间参数。测试方法,本机没有装jmeter,用apache ab做的测试,测试命令:

ab -n 100 -c 20 http://localhost:8080/bench/a/10"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值