多线程操作方式
public class UserService {
/**
* 堆内存 共享的,都会从这个区间来进行获取得到对应的对象
* 每个都会有个线程栈空间而已,但是会涉及到共享资源
* 那么堆共享资源的操作,应该涉及到互斥
* 这个需要来对其实现注意!
* 其实和lock锁原理一致;
*/
/**
* 方法区
*/
static int i = 10;
public void show (){
synchronized (this){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i--;
}
}
}
对应的操作代码:
public class CountdownLatchDemo1 {
public static void main(String[] args) {
UserService userService = new UserService();
final CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
latch.countDown();
userService.show();
System.out.println("对应的值是:"+UserService.i);
}).start();
}
try {
latch.await();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
画个图来进行对应的表示方式:
多个线程会去访问共享资源,但是共享如果没有被保护好,那么所有的都可以来进行对应的操作。
但是多个线程在使用同一个对象来调用方法的时候,每个线程都会另外起一个方法栈来调用方法,所以每个栈空间的会去访问到方法区或者是堆内存中的共享资源。
那么如果没有保护好,就会导致线程不安全的情况。所以考虑到这一点应该考虑到对应的解决方式:
@Service
@AllArgsConstructor
public class UserServiceImpl implements UserService {
private static final Lock LOCK = new ReentrantLock();
private static final Map<String,Object> MAP = new ConcurrentHashMap<>(255);
private final UserMapper userMapper;
/**
* 不存在线程共享的问题,所以可以安全的来进行使用
* @return
*/
// 一定要注意使用@Transactional注解的使用方式,会导致注解失效
@Override
public List<User> queryUserByCondition() {
UserExample userExample = new UserExample();
UserExample.Criteria criteria = userExample.createCriteria();
criteria.andIdIn(Arrays.asList(1,2,3,4));
List<User> users = userMapper.selectByExample(userExample);
return users;
}
// 如果多个线程中需要使用到共享资源,那么应该使用并发操作的变量来进行操作
public List<User> update(Integer id) {
Object constan_key = MAP.get("CONSTAN_KEY");
if (Objects.nonNull(constan_key)){
// doSomething.........
}else {
MAP.put("CONSTAN_KEY","helloworld");
}
// doOther.............
return null;
}
}
从理论中来,到实践中去,最终回归理论