0
# Process Management and Synchronization
1
2
MMKV provides robust multi-process synchronization capabilities, allowing safe concurrent access across Android processes with file locking, content change notifications, and automatic synchronization.
3
4
## Capabilities
5
6
### Process Locking
7
8
MMKV provides inter-process exclusive locking for safe concurrent access across multiple processes.
9
10
```java { .api }
11
/**
12
* Exclusively inter-process lock the MMKV instance.
13
* It will block and wait until it successfully locks the file.
14
* It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
15
*/
16
void lock();
17
18
/**
19
* Exclusively inter-process unlock the MMKV instance.
20
* It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
21
*/
22
void unlock();
23
24
/**
25
* Try exclusively inter-process lock the MMKV instance.
26
* It will not block if the file has already been locked by another process.
27
* It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
28
* @return True if successfully locked, otherwise return immediately with False
29
*/
30
boolean tryLock();
31
```
32
33
**Usage Examples:**
34
35
```java
36
// Create multi-process MMKV instance
37
MMKV sharedKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);
38
39
// Blocking lock - waits until lock is acquired
40
sharedKv.lock();
41
try {
42
// Critical section - only one process can access at a time
43
sharedKv.encode("shared_counter", sharedKv.decodeInt("shared_counter", 0) + 1);
44
sharedKv.encode("last_modified", System.currentTimeMillis());
45
} finally {
46
// Always unlock in finally block
47
sharedKv.unlock();
48
}
49
50
// Non-blocking lock attempt
51
if (sharedKv.tryLock()) {
52
try {
53
// Got the lock, perform operations
54
sharedKv.encode("optional_update", "updated");
55
} finally {
56
sharedKv.unlock();
57
}
58
} else {
59
Log.d("MMKV", "Could not acquire lock, skipping update");
60
}
61
```
62
63
### Data Synchronization
64
65
MMKV provides explicit synchronization methods for ensuring data persistence, though data is normally persisted immediately.
66
67
```java { .api }
68
/**
69
* Save all mmap memory to file synchronously.
70
* You don't need to call this, really, I mean it.
71
* Unless you worry about the device running out of battery.
72
*/
73
void sync();
74
75
/**
76
* Save all mmap memory to file asynchronously.
77
* No need to call this unless you worry about the device running out of battery.
78
*/
79
void async();
80
```
81
82
**Usage Examples:**
83
84
```java
85
MMKV kv = MMKV.mmkvWithID("important_data");
86
87
// Store critical data
88
kv.encode("critical_setting", importantValue);
89
90
// Force synchronous write to disk (usually not needed)
91
kv.sync();
92
93
// Or force asynchronous write
94
kv.async();
95
96
// Note: MMKV automatically persists data immediately, these calls are optional
97
```
98
99
### Content Change Notifications
100
101
MMKV provides inter-process content change notifications to detect when data is modified by other processes.
102
103
```java { .api }
104
/**
105
* Register for MMKV inter-process content change notification.
106
* The notification will trigger only when any method is manually called on the MMKV instance.
107
* For example checkContentChangedByOuterProcess().
108
* @param notify The notification handler
109
*/
110
static void registerContentChangeNotify(MMKVContentChangeNotification notify);
111
112
/**
113
* Unregister for MMKV inter-process content change notification.
114
*/
115
static void unregisterContentChangeNotify();
116
117
/**
118
* Check inter-process content change manually.
119
*/
120
void checkContentChangedByOuterProcess();
121
```
122
123
**Usage Examples:**
124
125
```java
126
// Set up content change notification
127
MMKV.registerContentChangeNotify(new MMKVContentChangeNotification() {
128
@Override
129
public void onContentChangedByOuterProcess(String mmapID) {
130
Log.d("MMKV", "Content changed in instance: " + mmapID);
131
132
// Refresh UI or reload data as needed
133
if ("shared_config".equals(mmapID)) {
134
reloadConfiguration();
135
}
136
}
137
});
138
139
// In your activity or service
140
MMKV sharedConfig = MMKV.mmkvWithID("shared_config", MMKV.MULTI_PROCESS_MODE);
141
142
// Periodically check for changes from other processes
143
private void checkForUpdates() {
144
sharedConfig.checkContentChangedByOuterProcess();
145
// If content changed, onContentChangedByOuterProcess() will be called
146
}
147
148
// Clean up when done
149
@Override
150
protected void onDestroy() {
151
super.onDestroy();
152
MMKV.unregisterContentChangeNotify();
153
}
154
```
155
156
### Process Mode Management
157
158
MMKV provides utilities for managing and validating process modes to prevent conflicts.
159
160
```java { .api }
161
/**
162
* Manually enable the process mode checker.
163
* By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
164
* If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
165
*/
166
static void enableProcessModeChecker();
167
168
/**
169
* Manually disable the process mode checker.
170
* By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
171
* If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
172
*/
173
static void disableProcessModeChecker();
174
175
/**
176
* Check if this instance is in multi-process mode.
177
* @return True if in multi-process mode, False otherwise
178
*/
179
boolean isMultiProcess();
180
181
/**
182
* Check if this instance is in read-only mode.
183
* @return True if in read-only mode, False otherwise
184
*/
185
boolean isReadOnly();
186
```
187
188
**Usage Examples:**
189
190
```java
191
// Enable strict process mode checking for debugging
192
MMKV.enableProcessModeChecker();
193
194
// Create instances
195
MMKV singleKv = MMKV.mmkvWithID("single_data", MMKV.SINGLE_PROCESS_MODE);
196
MMKV multiKv = MMKV.mmkvWithID("multi_data", MMKV.MULTI_PROCESS_MODE);
197
198
// Verify process modes
199
Log.d("MMKV", "Single KV multi-process: " + singleKv.isMultiProcess()); // false
200
Log.d("MMKV", "Multi KV multi-process: " + multiKv.isMultiProcess()); // true
201
202
// This would throw an exception if process mode checker is enabled
203
// and "multi_data" was previously opened with SINGLE_PROCESS_MODE
204
try {
205
MMKV conflictKv = MMKV.mmkvWithID("multi_data", MMKV.SINGLE_PROCESS_MODE);
206
} catch (IllegalArgumentException e) {
207
Log.e("MMKV", "Process mode conflict: " + e.getMessage());
208
}
209
210
// Disable checking for production
211
MMKV.disableProcessModeChecker();
212
```
213
214
### Anonymous Shared Memory for Inter-Process Communication
215
216
MMKV supports Anonymous Shared Memory (ashmem) for high-performance inter-process data sharing without disk persistence.
217
218
```java { .api }
219
/**
220
* Create an MMKV instance base on Anonymous Shared Memory, aka not synced to any disk files.
221
* @param context The context of Android App, usually from Application
222
* @param mmapID The unique ID of the MMKV instance
223
* @param size The maximum size of the underlying Anonymous Shared Memory.
224
* Anonymous Shared Memory on Android can't grow dynamically, must set an appropriate size on creation
225
* @param mode The process mode of the MMKV instance, defaults to SINGLE_PROCESS_MODE
226
* @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes)
227
* @throws RuntimeException if there's a runtime error
228
*/
229
static MMKV mmkvWithAshmemID(Context context, String mmapID, int size, int mode, String cryptKey);
230
231
/**
232
* @return The file descriptor of the ashmem of the MMKV file
233
*/
234
int ashmemFD();
235
236
/**
237
* @return The file descriptor of the ashmem of the MMKV crc file
238
*/
239
int ashmemMetaFD();
240
```
241
242
**Usage Examples:**
243
244
```java
245
// Create ashmem instance for inter-process communication
246
MMKV ashmemKv = MMKV.mmkvWithAshmemID(
247
this,
248
"ipc_data",
249
1024 * 1024, // 1MB max size
250
MMKV.MULTI_PROCESS_MODE,
251
null // No encryption
252
);
253
254
// Use like regular MMKV instance
255
ashmemKv.encode("shared_message", "Hello from process A");
256
ashmemKv.encode("shared_timestamp", System.currentTimeMillis());
257
258
// Get file descriptors for passing to other processes
259
int dataFD = ashmemKv.ashmemFD();
260
int metaFD = ashmemKv.ashmemMetaFD();
261
262
// Pass these FDs to other processes via Binder/AIDL
263
// The receiving process can create MMKV instance from FDs
264
```
265
266
### Multi-Process Best Practices
267
268
Guidelines and patterns for effective multi-process MMKV usage.
269
270
```java
271
// Example multi-process architecture
272
public class SharedDataManager {
273
private static final String SHARED_INSTANCE_ID = "app_shared_data";
274
private final MMKV sharedKv;
275
276
public SharedDataManager(Context context) {
277
// Always use MULTI_PROCESS_MODE for shared data
278
sharedKv = MMKV.mmkvWithID(SHARED_INSTANCE_ID, MMKV.MULTI_PROCESS_MODE);
279
280
// Set up change notifications
281
MMKV.registerContentChangeNotify(this::onContentChanged);
282
}
283
284
public void updateSharedConfig(String key, Object value) {
285
sharedKv.lock();
286
try {
287
// Update with timestamp for conflict resolution
288
sharedKv.encode(key + "_timestamp", System.currentTimeMillis());
289
290
if (value instanceof String) {
291
sharedKv.encode(key, (String) value);
292
} else if (value instanceof Integer) {
293
sharedKv.encode(key, (Integer) value);
294
}
295
// Handle other types...
296
297
} finally {
298
sharedKv.unlock();
299
}
300
}
301
302
public <T> T getSharedConfig(String key, Class<T> type, T defaultValue) {
303
// Check for updates from other processes
304
sharedKv.checkContentChangedByOuterProcess();
305
306
if (type == String.class) {
307
return (T) sharedKv.decodeString(key, (String) defaultValue);
308
} else if (type == Integer.class) {
309
return (T) Integer.valueOf(sharedKv.decodeInt(key, (Integer) defaultValue));
310
}
311
// Handle other types...
312
313
return defaultValue;
314
}
315
316
private void onContentChanged(String mmapID) {
317
if (SHARED_INSTANCE_ID.equals(mmapID)) {
318
// Notify UI components about data changes
319
LocalBroadcastManager.getInstance(context)
320
.sendBroadcast(new Intent("SHARED_DATA_CHANGED"));
321
}
322
}
323
}
324
```
325
326
## Types
327
328
```java { .api }
329
/**
330
* Inter-process content change notification.
331
* Triggered by any method call, such as getXXX() or setXXX() or checkContentChangedByOuterProcess().
332
*/
333
interface MMKVContentChangeNotification {
334
/**
335
* Inter-process content change notification.
336
* Triggered by any method call, such as getXXX() or setXXX() or checkContentChangedByOuterProcess().
337
* @param mmapID The unique ID of the changed MMKV instance
338
*/
339
void onContentChangedByOuterProcess(String mmapID);
340
}
341
342
/**
343
* A helper class for MMKV based on Anonymous Shared Memory.
344
*/
345
class ParcelableMMKV implements Parcelable {
346
/**
347
* Create from existing MMKV instance
348
* @param mmkv The MMKV instance to wrap
349
*/
350
ParcelableMMKV(MMKV mmkv);
351
352
/**
353
* Convert back to MMKV instance
354
* @return MMKV instance, or null if invalid
355
*/
356
MMKV toMMKV();
357
358
// Parcelable implementation for passing between processes
359
int describeContents();
360
void writeToParcel(Parcel dest, int flags);
361
static final Parcelable.Creator<ParcelableMMKV> CREATOR;
362
}
363
364
/**
365
* A helper class for getting process information
366
*/
367
class MMKVContentProvider extends ContentProvider {
368
/**
369
* Get process name by process ID
370
* @param context Application context
371
* @param pid Process ID
372
* @return Process name or empty string if not found
373
*/
374
static String getProcessNameByPID(Context context, int pid);
375
376
/**
377
* Get content provider URI for ashmem operations
378
* @param context Application context
379
* @return Content provider URI, or null if not configured
380
*/
381
static Uri contentUri(Context context);
382
}
383
```
384
385
## Process Mode Constants
386
387
```java { .api }
388
/**
389
* Single-process mode. The default mode on an MMKV instance.
390
*/
391
static final int SINGLE_PROCESS_MODE = 1;
392
393
/**
394
* Multi-process mode.
395
* To enable multi-process accessing of an MMKV instance, you must set this mode whenever you getting that instance.
396
*/
397
static final int MULTI_PROCESS_MODE = 2;
398
399
/**
400
* Read-only mode.
401
*/
402
static final int READ_ONLY_MODE = 32;
403
```
404
405
## Performance Considerations
406
407
- **Single-process mode**: Fastest performance, no locking overhead
408
- **Multi-process mode**: Slight performance overhead due to file locking
409
- **Ashmem mode**: Best for temporary data sharing between processes
410
- **Content change notifications**: Minimal overhead, triggered only on manual checks
411
- **Process mode checker**: Should be disabled in production builds for optimal performance