zookeeper实现分布式锁

zookeeper实现分布式锁

一、简介

分布式环境下,需要访问共享变量时,需要分布式锁

二、安装zookeeper

启动命令

bin/zookeeper-server-start.sh config/zookeeper.properties
三、Maven依赖
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.9.0</version>
</dependency>
四、基于zookeeper实现分布式锁伪代码
InterProcessMutex lock = new InterProcessMutex(client, lockPath);
if ( lock.acquire(maxWait, waitUnit) ) {
    try {
        // do some work inside of the critical section here
    } finally {
        lock.release();
    }
}
五、无锁代码
package zookeeper;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by zhengyong on 16/11/24.
 */
public class NoLock {

    private static int             count           = 0;

    private static ExecutorService executorService = Executors.newFixedThreadPool(10);

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

        // 创建200个线程
        for (int i = 0; i < 200; i++) {
            final int index = i + 1;
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    try {
                        count("Thread-" + index);
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();
    }

    /**
     * 统计数量
     *
     * @param threadName 线程名称
     * @throws Exception
     */
    private static void count(final String threadName) throws Exception {
        count++;
        System.out.println(String.format("threadName %s acquire lock, count = %d", threadName, count));
    }
}

运行结果:不对, 71出现几次

threadName Thread-5 acquire lock, count = 5
threadName Thread-9 acquire lock, count = 9
threadName Thread-8 acquire lock, count = 8
threadName Thread-7 acquire lock, count = 7
threadName Thread-3 acquire lock, count = 3
threadName Thread-4 acquire lock, count = 4
threadName Thread-1 acquire lock, count = 1
threadName Thread-10 acquire lock, count = 10
threadName Thread-6 acquire lock, count = 6
threadName Thread-2 acquire lock, count = 2
threadName Thread-15 acquire lock, count = 15
threadName Thread-12 acquire lock, count = 12
threadName Thread-13 acquire lock, count = 13
threadName Thread-17 acquire lock, count = 17
threadName Thread-18 acquire lock, count = 18
threadName Thread-20 acquire lock, count = 20
threadName Thread-14 acquire lock, count = 14
threadName Thread-11 acquire lock, count = 11
threadName Thread-19 acquire lock, count = 19
threadName Thread-16 acquire lock, count = 16
threadName Thread-24 acquire lock, count = 24
threadName Thread-25 acquire lock, count = 25
threadName Thread-22 acquire lock, count = 22
threadName Thread-21 acquire lock, count = 21
threadName Thread-23 acquire lock, count = 23
threadName Thread-26 acquire lock, count = 26
threadName Thread-29 acquire lock, count = 29
threadName Thread-30 acquire lock, count = 30
threadName Thread-28 acquire lock, count = 28
threadName Thread-27 acquire lock, count = 27
threadName Thread-31 acquire lock, count = 31
threadName Thread-32 acquire lock, count = 32
threadName Thread-33 acquire lock, count = 33
threadName Thread-34 acquire lock, count = 34
threadName Thread-35 acquire lock, count = 35
threadName Thread-36 acquire lock, count = 36
threadName Thread-37 acquire lock, count = 37
threadName Thread-38 acquire lock, count = 38
threadName Thread-40 acquire lock, count = 39
threadName Thread-39 acquire lock, count = 40
threadName Thread-41 acquire lock, count = 41
threadName Thread-43 acquire lock, count = 42
threadName Thread-42 acquire lock, count = 43
threadName Thread-44 acquire lock, count = 44
threadName Thread-45 acquire lock, count = 45
threadName Thread-46 acquire lock, count = 47
threadName Thread-48 acquire lock, count = 48
threadName Thread-47 acquire lock, count = 47
threadName Thread-49 acquire lock, count = 49
threadName Thread-50 acquire lock, count = 50
threadName Thread-53 acquire lock, count = 52
threadName Thread-52 acquire lock, count = 52
threadName Thread-51 acquire lock, count = 51
threadName Thread-55 acquire lock, count = 54
threadName Thread-54 acquire lock, count = 53
threadName Thread-56 acquire lock, count = 55
threadName Thread-57 acquire lock, count = 56
threadName Thread-58 acquire lock, count = 57
threadName Thread-60 acquire lock, count = 59
threadName Thread-59 acquire lock, count = 58
threadName Thread-62 acquire lock, count = 61
threadName Thread-64 acquire lock, count = 63
threadName Thread-61 acquire lock, count = 60
threadName Thread-63 acquire lock, count = 62
threadName Thread-65 acquire lock, count = 64
threadName Thread-67 acquire lock, count = 66
threadName Thread-66 acquire lock, count = 65
threadName Thread-68 acquire lock, count = 67
threadName Thread-69 acquire lock, count = 68
threadName Thread-70 acquire lock, count = 69
threadName Thread-72 acquire lock, count = 71
threadName Thread-71 acquire lock, count = 71
threadName Thread-74 acquire lock, count = 72
threadName Thread-75 acquire lock, count = 73
threadName Thread-73 acquire lock, count = 71
threadName Thread-76 acquire lock, count = 74
threadName Thread-77 acquire lock, count = 75
threadName Thread-78 acquire lock, count = 76
threadName Thread-80 acquire lock, count = 78
threadName Thread-79 acquire lock, count = 77
threadName Thread-81 acquire lock, count = 79
threadName Thread-85 acquire lock, count = 82
threadName Thread-86 acquire lock, count = 84
threadName Thread-83 acquire lock, count = 80
threadName Thread-82 acquire lock, count = 79
threadName Thread-84 acquire lock, count = 81
threadName Thread-87 acquire lock, count = 84
threadName Thread-88 acquire lock, count = 85
threadName Thread-90 acquire lock, count = 86
threadName Thread-89 acquire lock, count = 86
threadName Thread-92 acquire lock, count = 88
threadName Thread-93 acquire lock, count = 89
threadName Thread-95 acquire lock, count = 91
threadName Thread-91 acquire lock, count = 87
threadName Thread-97 acquire lock, count = 93
threadName Thread-96 acquire lock, count = 92
threadName Thread-94 acquire lock, count = 90
threadName Thread-98 acquire lock, count = 94
threadName Thread-100 acquire lock, count = 96
threadName Thread-99 acquire lock, count = 95
threadName Thread-102 acquire lock, count = 97
threadName Thread-105 acquire lock, count = 101
threadName Thread-104 acquire lock, count = 100
threadName Thread-108 acquire lock, count = 103
threadName Thread-103 acquire lock, count = 99
threadName Thread-101 acquire lock, count = 98
threadName Thread-107 acquire lock, count = 102
threadName Thread-106 acquire lock, count = 102
threadName Thread-109 acquire lock, count = 104
threadName Thread-110 acquire lock, count = 105
threadName Thread-111 acquire lock, count = 106
threadName Thread-117 acquire lock, count = 112
threadName Thread-114 acquire lock, count = 110
threadName Thread-115 acquire lock, count = 109
threadName Thread-112 acquire lock, count = 107
threadName Thread-113 acquire lock, count = 108
threadName Thread-119 acquire lock, count = 114
threadName Thread-118 acquire lock, count = 113
threadName Thread-116 acquire lock, count = 111
threadName Thread-120 acquire lock, count = 115
threadName Thread-121 acquire lock, count = 116
threadName Thread-124 acquire lock, count = 119
threadName Thread-126 acquire lock, count = 121
threadName Thread-127 acquire lock, count = 122
threadName Thread-123 acquire lock, count = 118
threadName Thread-122 acquire lock, count = 117
threadName Thread-129 acquire lock, count = 124
threadName Thread-128 acquire lock, count = 123
threadName Thread-125 acquire lock, count = 120
threadName Thread-130 acquire lock, count = 125
threadName Thread-134 acquire lock, count = 129
threadName Thread-131 acquire lock, count = 126
threadName Thread-139 acquire lock, count = 134
threadName Thread-137 acquire lock, count = 132
threadName Thread-135 acquire lock, count = 130
threadName Thread-136 acquire lock, count = 131
threadName Thread-133 acquire lock, count = 128
threadName Thread-132 acquire lock, count = 127
threadName Thread-138 acquire lock, count = 133
threadName Thread-140 acquire lock, count = 135
threadName Thread-142 acquire lock, count = 137
threadName Thread-141 acquire lock, count = 136
threadName Thread-143 acquire lock, count = 138
threadName Thread-144 acquire lock, count = 139
threadName Thread-145 acquire lock, count = 140
threadName Thread-146 acquire lock, count = 141
threadName Thread-147 acquire lock, count = 142
threadName Thread-149 acquire lock, count = 144
threadName Thread-148 acquire lock, count = 143
threadName Thread-150 acquire lock, count = 145
threadName Thread-151 acquire lock, count = 146
threadName Thread-152 acquire lock, count = 147
threadName Thread-153 acquire lock, count = 148
threadName Thread-154 acquire lock, count = 149
threadName Thread-156 acquire lock, count = 151
threadName Thread-155 acquire lock, count = 150
threadName Thread-158 acquire lock, count = 153
threadName Thread-159 acquire lock, count = 154
threadName Thread-157 acquire lock, count = 152
threadName Thread-160 acquire lock, count = 155
threadName Thread-163 acquire lock, count = 158
threadName Thread-164 acquire lock, count = 159
threadName Thread-162 acquire lock, count = 157
threadName Thread-161 acquire lock, count = 156
threadName Thread-165 acquire lock, count = 160
threadName Thread-166 acquire lock, count = 161
threadName Thread-167 acquire lock, count = 162
threadName Thread-169 acquire lock, count = 164
threadName Thread-170 acquire lock, count = 165
threadName Thread-168 acquire lock, count = 163
threadName Thread-171 acquire lock, count = 166
threadName Thread-172 acquire lock, count = 167
threadName Thread-173 acquire lock, count = 168
threadName Thread-174 acquire lock, count = 169
threadName Thread-175 acquire lock, count = 170
threadName Thread-176 acquire lock, count = 171
threadName Thread-177 acquire lock, count = 172
threadName Thread-178 acquire lock, count = 173
threadName Thread-179 acquire lock, count = 174
threadName Thread-180 acquire lock, count = 175
threadName Thread-181 acquire lock, count = 176
threadName Thread-182 acquire lock, count = 177
threadName Thread-183 acquire lock, count = 178
threadName Thread-186 acquire lock, count = 181
threadName Thread-188 acquire lock, count = 183
threadName Thread-185 acquire lock, count = 180
threadName Thread-184 acquire lock, count = 179
threadName Thread-190 acquire lock, count = 185
threadName Thread-189 acquire lock, count = 184
threadName Thread-187 acquire lock, count = 182
threadName Thread-192 acquire lock, count = 187
threadName Thread-193 acquire lock, count = 188
threadName Thread-195 acquire lock, count = 190
threadName Thread-196 acquire lock, count = 191
threadName Thread-198 acquire lock, count = 193
threadName Thread-191 acquire lock, count = 187
threadName Thread-199 acquire lock, count = 194
threadName Thread-197 acquire lock, count = 192
threadName Thread-194 acquire lock, count = 189
threadName Thread-200 acquire lock, count = 195
六、加锁代码
package zookeeper;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.utils.ZKPaths;
import org.apache.zookeeper.ZooKeeper;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Created by zhengyong on 16/11/24.
 */
public class DistributedLock {

    private static final int       sessionTimeout  = 15000;
    private static final String    ZK_HOST         = "127.0.0.1:2181";
    private static final String    ZK_PATH         = "/zkPath";
    private static int             count           = 0;

    private static ExecutorService executorService = Executors.newFixedThreadPool(10);

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

        ZooKeeper zookeeper = new ZooKeeper(ZK_HOST, sessionTimeout, null);
        ZKPaths.mkdirs(zookeeper, ZK_PATH);

        // 创建200个线程
        for (int i = 0; i < 200; i++) {
            final int index = i + 1;
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    try {
                        count("Thread-" + index);
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();
    }

    /**
     * 统计count数
     *
     * @param threadName 线程名称
     * @throws Exception
     */
    private static void count(final String threadName) throws Exception {

        CuratorFramework localCuratorClient = CuratorFrameworkFactory.builder().connectString(ZK_HOST).sessionTimeoutMs(sessionTimeout).retryPolicy(new ExponentialBackoffRetry(1000,
                                                                                                                                                                                10,
                                                                                                                                                                                5000)).build();
        localCuratorClient.start();

        // 分布式锁逻辑
        lock(localCuratorClient, threadName);

        // 系统关闭的时候请调用nodeCache.close();
    }

    /**
     * 分布式锁逻辑
     * 
     * @param curatorClient zkClient
     * @param threadName 线程名称
     * @throws Exception
     */
    private static void lock(CuratorFramework curatorClient, final String threadName) throws Exception {
        InterProcessMutex lock = new InterProcessMutex(curatorClient, ZK_PATH);
        if (lock.acquire(2000, TimeUnit.MILLISECONDS)) {
            try {
                // do some work inside of the critical section here
                count++;
                System.out.println(String.format("threadName %s acquire lock, count = %d", threadName, count));
            } finally {
                lock.release();
            }
        }
    }
}

运行结果:正常

threadName Thread-8 acquire lock, count = 1
threadName Thread-6 acquire lock, count = 2
threadName Thread-10 acquire lock, count = 3
threadName Thread-7 acquire lock, count = 4
threadName Thread-3 acquire lock, count = 5
threadName Thread-4 acquire lock, count = 6
threadName Thread-9 acquire lock, count = 7
threadName Thread-5 acquire lock, count = 8
threadName Thread-1 acquire lock, count = 9
threadName Thread-2 acquire lock, count = 10
threadName Thread-11 acquire lock, count = 11
threadName Thread-12 acquire lock, count = 12
threadName Thread-13 acquire lock, count = 13
threadName Thread-14 acquire lock, count = 14
threadName Thread-16 acquire lock, count = 15
threadName Thread-15 acquire lock, count = 16
threadName Thread-17 acquire lock, count = 17
threadName Thread-18 acquire lock, count = 18
threadName Thread-19 acquire lock, count = 19
threadName Thread-20 acquire lock, count = 20
threadName Thread-21 acquire lock, count = 21
threadName Thread-22 acquire lock, count = 22
threadName Thread-23 acquire lock, count = 23
threadName Thread-24 acquire lock, count = 24
threadName Thread-25 acquire lock, count = 25
threadName Thread-26 acquire lock, count = 26
threadName Thread-27 acquire lock, count = 27
threadName Thread-28 acquire lock, count = 28
threadName Thread-29 acquire lock, count = 29
threadName Thread-30 acquire lock, count = 30
threadName Thread-31 acquire lock, count = 31
threadName Thread-32 acquire lock, count = 32
threadName Thread-33 acquire lock, count = 33
threadName Thread-34 acquire lock, count = 34
threadName Thread-35 acquire lock, count = 35
threadName Thread-36 acquire lock, count = 36
threadName Thread-37 acquire lock, count = 37
threadName Thread-38 acquire lock, count = 38
threadName Thread-39 acquire lock, count = 39
threadName Thread-40 acquire lock, count = 40
threadName Thread-41 acquire lock, count = 41
threadName Thread-42 acquire lock, count = 42
threadName Thread-43 acquire lock, count = 43
threadName Thread-44 acquire lock, count = 44
threadName Thread-45 acquire lock, count = 45
threadName Thread-46 acquire lock, count = 46
threadName Thread-47 acquire lock, count = 47
threadName Thread-48 acquire lock, count = 48
threadName Thread-49 acquire lock, count = 49
threadName Thread-50 acquire lock, count = 50
threadName Thread-51 acquire lock, count = 51
threadName Thread-52 acquire lock, count = 52
threadName Thread-53 acquire lock, count = 53
threadName Thread-54 acquire lock, count = 54
threadName Thread-55 acquire lock, count = 55
threadName Thread-56 acquire lock, count = 56
threadName Thread-57 acquire lock, count = 57
threadName Thread-58 acquire lock, count = 58
threadName Thread-59 acquire lock, count = 59
threadName Thread-60 acquire lock, count = 60
threadName Thread-61 acquire lock, count = 61
threadName Thread-62 acquire lock, count = 62
threadName Thread-63 acquire lock, count = 63
threadName Thread-64 acquire lock, count = 64
threadName Thread-65 acquire lock, count = 65
threadName Thread-66 acquire lock, count = 66
threadName Thread-67 acquire lock, count = 67
threadName Thread-68 acquire lock, count = 68
threadName Thread-69 acquire lock, count = 69
threadName Thread-72 acquire lock, count = 70
threadName Thread-70 acquire lock, count = 71
threadName Thread-71 acquire lock, count = 72
threadName Thread-73 acquire lock, count = 73
threadName Thread-74 acquire lock, count = 74
threadName Thread-75 acquire lock, count = 75
threadName Thread-76 acquire lock, count = 76
threadName Thread-77 acquire lock, count = 77
threadName Thread-78 acquire lock, count = 78
threadName Thread-79 acquire lock, count = 79
threadName Thread-80 acquire lock, count = 80
threadName Thread-81 acquire lock, count = 81
threadName Thread-82 acquire lock, count = 82
threadName Thread-83 acquire lock, count = 83
threadName Thread-84 acquire lock, count = 84
threadName Thread-85 acquire lock, count = 85
threadName Thread-86 acquire lock, count = 86
threadName Thread-87 acquire lock, count = 87
threadName Thread-88 acquire lock, count = 88
threadName Thread-89 acquire lock, count = 89
threadName Thread-90 acquire lock, count = 90
threadName Thread-91 acquire lock, count = 91
threadName Thread-92 acquire lock, count = 92
threadName Thread-93 acquire lock, count = 93
threadName Thread-94 acquire lock, count = 94
threadName Thread-95 acquire lock, count = 95
threadName Thread-96 acquire lock, count = 96
threadName Thread-97 acquire lock, count = 97
threadName Thread-98 acquire lock, count = 98
threadName Thread-99 acquire lock, count = 99
threadName Thread-100 acquire lock, count = 100
threadName Thread-101 acquire lock, count = 101
threadName Thread-102 acquire lock, count = 102
threadName Thread-103 acquire lock, count = 103
threadName Thread-104 acquire lock, count = 104
threadName Thread-105 acquire lock, count = 105
threadName Thread-106 acquire lock, count = 106
threadName Thread-107 acquire lock, count = 107
threadName Thread-108 acquire lock, count = 108
threadName Thread-109 acquire lock, count = 109
threadName Thread-110 acquire lock, count = 110
threadName Thread-111 acquire lock, count = 111
threadName Thread-113 acquire lock, count = 112
threadName Thread-112 acquire lock, count = 113
threadName Thread-114 acquire lock, count = 114
threadName Thread-115 acquire lock, count = 115
threadName Thread-116 acquire lock, count = 116
threadName Thread-117 acquire lock, count = 117
threadName Thread-118 acquire lock, count = 118
threadName Thread-119 acquire lock, count = 119
threadName Thread-120 acquire lock, count = 120
threadName Thread-121 acquire lock, count = 121
threadName Thread-122 acquire lock, count = 122
threadName Thread-123 acquire lock, count = 123
threadName Thread-125 acquire lock, count = 124
threadName Thread-124 acquire lock, count = 125
threadName Thread-126 acquire lock, count = 126
threadName Thread-127 acquire lock, count = 127
threadName Thread-128 acquire lock, count = 128
threadName Thread-129 acquire lock, count = 129
threadName Thread-130 acquire lock, count = 130
threadName Thread-131 acquire lock, count = 131
threadName Thread-132 acquire lock, count = 132
threadName Thread-133 acquire lock, count = 133
threadName Thread-134 acquire lock, count = 134
threadName Thread-135 acquire lock, count = 135
threadName Thread-137 acquire lock, count = 136
threadName Thread-136 acquire lock, count = 137
threadName Thread-138 acquire lock, count = 138
threadName Thread-139 acquire lock, count = 139
threadName Thread-140 acquire lock, count = 140
threadName Thread-141 acquire lock, count = 141
threadName Thread-142 acquire lock, count = 142
threadName Thread-143 acquire lock, count = 143
threadName Thread-144 acquire lock, count = 144
threadName Thread-145 acquire lock, count = 145
threadName Thread-146 acquire lock, count = 146
threadName Thread-147 acquire lock, count = 147
threadName Thread-148 acquire lock, count = 148
threadName Thread-149 acquire lock, count = 149
threadName Thread-150 acquire lock, count = 150
threadName Thread-151 acquire lock, count = 151
threadName Thread-152 acquire lock, count = 152
threadName Thread-153 acquire lock, count = 153
threadName Thread-154 acquire lock, count = 154
threadName Thread-155 acquire lock, count = 155
threadName Thread-156 acquire lock, count = 156
threadName Thread-157 acquire lock, count = 157
threadName Thread-158 acquire lock, count = 158
threadName Thread-159 acquire lock, count = 159
threadName Thread-160 acquire lock, count = 160
threadName Thread-161 acquire lock, count = 161
threadName Thread-162 acquire lock, count = 162
threadName Thread-163 acquire lock, count = 163
threadName Thread-164 acquire lock, count = 164
threadName Thread-165 acquire lock, count = 165
threadName Thread-166 acquire lock, count = 166
threadName Thread-167 acquire lock, count = 167
threadName Thread-168 acquire lock, count = 168
threadName Thread-169 acquire lock, count = 169
threadName Thread-170 acquire lock, count = 170
threadName Thread-171 acquire lock, count = 171
threadName Thread-172 acquire lock, count = 172
threadName Thread-173 acquire lock, count = 173
threadName Thread-174 acquire lock, count = 174
threadName Thread-175 acquire lock, count = 175
threadName Thread-176 acquire lock, count = 176
threadName Thread-177 acquire lock, count = 177
threadName Thread-178 acquire lock, count = 178
threadName Thread-179 acquire lock, count = 179
threadName Thread-180 acquire lock, count = 180
threadName Thread-181 acquire lock, count = 181
threadName Thread-182 acquire lock, count = 182
threadName Thread-183 acquire lock, count = 183
threadName Thread-184 acquire lock, count = 184
threadName Thread-185 acquire lock, count = 185
threadName Thread-186 acquire lock, count = 186
threadName Thread-187 acquire lock, count = 187
threadName Thread-188 acquire lock, count = 188
threadName Thread-189 acquire lock, count = 189
threadName Thread-190 acquire lock, count = 190
threadName Thread-191 acquire lock, count = 191
threadName Thread-192 acquire lock, count = 192
threadName Thread-193 acquire lock, count = 193
threadName Thread-194 acquire lock, count = 194
threadName Thread-195 acquire lock, count = 195
threadName Thread-196 acquire lock, count = 196
threadName Thread-197 acquire lock, count = 197
threadName Thread-198 acquire lock, count = 198
threadName Thread-199 acquire lock, count = 199
threadName Thread-200 acquire lock, count = 200
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值